使用tpl取回task中的运行结果的三种方式(代码片段)

C_supreme C_supreme     2022-11-05     746

关键词:

概念:TPL( Task Parallel Library) 任务并行库

使用Task类执行多线程操作要比直接使用自己手工创建Thread效率高很多。

默认情况下,TPL使用线程池中的线程执行Task,但是工作结束之后,调用者线程怎么取回执行线程的工作结果呢?

这里有三种方法:

1.使用经典的线程同步手段:

可以使用线程同步对象。比如ManualResetEvent

在任务方法中设置ManualResetEvent状态为Signaled

调用者示例代码:

示例代码:

/// <summary>
        /// 用于保存处理结果的共享资源
        /// </summary>
        private static long result = 0;
        /// <summary>
        /// 用于通知启动任务的线程处理工作已完成
        /// </summary>
        static ManualResetEvent mre = new ManualResetEvent(false);
        static void Main(string[] args)
        
            Action<object> taskMethod = (end) =>
            
                long sum = 0;
                for (int i = 1; i < (int) end; i++)
                    sum += i;
                //保存处理结果(使用Interlocked实现原子操作,无需加锁)
                Interlocked.Exchange(ref result, sum);
                //通知调用者,工作已经完成,可以取回结果了
                mre.Set();
            ;
            //启动异步任务
            Task tsk = new Task(taskMethod,1000000);
            tsk.Start();
            //等待并行处理的完成已取回结果
            mre.WaitOne();
            Console.WriteLine("程序运行结果为0",Program.result);
            Console.ReadKey();
        

这种方法混杂了TPL与传统多线程开发方式,不推荐使用

2.使用Task<T>,Result属性

示例代码:

static void Main(string[] args)
        
            Func<object, long> del = (end) =>
            
                long sum = 0;
                for (int i = 1; i < (int) end; i++)
                    sum += i;
                return sum;
            ;
            Task<long> tsk = new Task<long>(del,100000);
            tsk.Start();
            Console.WriteLine("程序运行结果为0",tsk.Result);
            Console.ReadKey();
        

这种编程方式代码简洁,开发中可用,但是调用者线程必须阻塞等待任务结束。不适合在服务端应用中使用

3.基于回调模式的结果取回

TPL中有一个ContinueWith()方法,可用于创建前赴后继的工作任务

这里调用者线程不是阻塞等待的。适合在服务端应用程序中使用。

示例代码

static void Main(string[] args)
        
            Func<object, long> ProcessData = (end) =>
            
                long sum = 0;
                for (int i = 1; i < (int)end; i++)
                
                    sum += i;
                    throw new DivideByZeroException();
                
                return sum;
            ;
            //用于取回处理结果的函数
            Action<Task<long>> GetResult = (finishedTask) =>
            
                //依据任务状态,决定后继处理工作
                if (finishedTask.IsFaulted)
                    Console.WriteLine("任务在执行时发生异常:0", finishedTask.Exception);
                else
                    Console.Write("程序运行结果为0", finishedTask.Result);
            ;

            //创建并行处理数据的任务对象
            Task<long> tskProcess = new Task<long>(ProcessData, 1000000);

            //当数据处理结束时,自动启动下一个工作任务,取回上一任务的处理结果
            Task tskGetResult = tskProcess.ContinueWith(GetResult);

            //开始并行处理数据……
            tskProcess.Start();


            Console.ReadKey();
        

 

js的三种使用方式/css的三种使用方式/js中的dom事件模型/js中匿名函数的书写及调用/媒体查询@media的三种使用方式

一、JS的三种使用方式      1、html标签中内嵌JS(不提倡使用。)            <buttononclick="javascript:alert(‘你真点啊。‘)">有本事点我呀!!!!</button>  &nbs 查看详情

java-多线程-创建线程的三种方式

...程不会提高程序运行速度,但是会提高运行效率。创建和使用线程的三种方式继承Thr 查看详情

日期处理的三种方式(代码片段)

一:使用注解的方式@JsonFormat注解该注解加在实体类中的日期类型上,可以将返回的Json字符串中的时间戳转换为具体时间@JsonFormat(pattern="yyyy-MM-ddHH:mm:ss",timezone="GMT+8")privateDateupdateTime;?我们通过使用@JsonFormat可以很好的解决:后台到... 查看详情

java中的三种注释

...容2.多行注释,可以注释一段文字3.JavaDOC文档注释,对代码中的内容及一些内容进行描述 查看详情

flowable服务任务执行的三种方式(代码片段)

前面和小伙伴们分别聊了Flowable中的ReceiveTask和UserTask,今天我们来看看另外一个比较常见的Task-->ServiceTask。1.ServiceTaskServiceTask从名字上看就是服务任务,它的图标一般是像下面这样:ServiceTask一般由系统自动完成... 查看详情

flowable服务任务执行的三种方式(代码片段)

前面和小伙伴们分别聊了Flowable中的ReceiveTask和UserTask,今天我们来看看另外一个比较常见的Task-->ServiceTask。1.ServiceTaskServiceTask从名字上看就是服务任务,它的图标一般是像下面这样:ServiceTask一般由系统自动完成... 查看详情

struts中的数据处理的三种方式

 Struts中的数据处理的三种方式: publicclassDataActionextendsActionSupport{@OverridepublicStringexecute()throwsException{//1.请求数据封装;2.调用Service处理业务逻辑,拿到结果数据3.数据保存到域中/**//Struts中对数据操作,方式1:直接拿到Se... 查看详情

markdownjs库的三种使用方式(代码片段)

查看详情

ubuntu18.04下cuda.cu在c/c++中的三种使用方式(代码片段)

文章目录操作系统前提第一种方式使用cuda函数文件的内容如下开始编译第二种方式使用cuda函数第三种方式使用cuda函数参考网站操作系统ubuntu18.04前提想要在.c文件中使用cuda的函数,即.cu的内容安装nvcc不是这里的内容,... 查看详情

ubuntu18.04下cuda.cu在c/c++中的三种使用方式(代码片段)

文章目录操作系统前提第一种方式使用cuda函数文件的内容如下开始编译第二种方式使用cuda函数第三种方式使用cuda函数参考网站操作系统ubuntu18.04前提想要在.c文件中使用cuda的函数,即.cu的内容安装nvcc不是这里的内容,... 查看详情

ubuntu18.04下cuda.cu在c/c++中的三种使用方式(代码片段)

文章目录操作系统前提第一种方式使用cuda函数文件的内容如下开始编译第二种方式使用cuda函数第三种方式使用cuda函数操作系统ubuntu18.04前提想要在.c文件中使用cuda的函数,即.cu的内容安装nvcc不是这里的内容,但是确保... 查看详情

php命令行脚本接收传入参数的三种方式(代码片段)

通常PHP都做http方式请求了,可以使用GETorPOST方式接收参数,有些时候需要在shell命令下把PHP当作脚本执行,比如定时任务。这就涉及到在shell命令下如何给php传参的问题,通常有三种方式传参。一、使用$argvor$argc参数接收<?php/*... 查看详情

c++中的三种继承方式(代码片段)

...bsp;2,有趣的问题:   1,是否可以将继承语句中的public换成 查看详情

spring中@value的三种使用方式(代码片段)

Spring中@Value的三种使用方式文章目录Spring中@Value的三种使用方式@Value 的作用是什么?我们可以从 Spring官方文档 里面找到这样的一句话:接下来我们看下 @Value 注入外部属性的三种方式:1.注入普通属... 查看详情

selenium常用的三种等待方式(代码片段)

...作成功之后才能进行下一步操作等,这时候,我们就需要使用等待,来判断上一步操作是否完成,什么时候可以进行下一步操作。如果说上一步操作如果花费的时间较长,还没有完成,就去进行下一步操作,这时就会产生无法定... 查看详情

java中的三种跳出多重循环的方式(代码片段)

使用带有标记的break语句,break默认是结束当前的while/for/case语句,但是当要一次结束多层嵌套的时候可以通过添加标记的方法,具体操作如下:Stringa1="";Stringb1="";here:for(inti=1;i<=4;i++... 查看详情

java中的三种跳出多重循环的方式(代码片段)

使用带有标记的break语句,break默认是结束当前的while/for/case语句,但是当要一次结束多层嵌套的时候可以通过添加标记的方法,具体操作如下:Stringa1="";Stringb1="";here:for(inti=1;i<=4;i++... 查看详情

springboot的三种启动方式(代码片段)

...springboot是一个框架,它依赖于spring,在过去我们使用spring项目的时候,需要大量各种繁琐的配置文件才能让spring跑起来,但自从有了springboot之后,它简化了使用方式,做到了无xml文件的配置即可运行,... 查看详情