使用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(代码片

C#异步方法async/await的三种返回类型

java中数组遍历的三种方式

Windows 模拟和 TPL

Flowable 服务任务执行的三种方式

Flowable 服务任务执行的三种方式