使用TPL取回Task中的运行结果的三种方式
Posted C_supreme
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用TPL取回Task中的运行结果的三种方式相关的知识,希望对你有一定的参考价值。
概念: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(); }
以上是关于使用TPL取回Task中的运行结果的三种方式的主要内容,如果未能解决你的问题,请参考以下文章
Android 返回堆栈管理打印 Android 中当前运行的 Activity 任务栈信息 | Activity 任务栈信息分析 | Activity 在相同 Stack 中的不同 Task(代码片