码迷,mamicode.com
首页 > 其他好文 > 详细

使用TPL取回Task中的运行结果的三种方式

时间:2018-04-22 21:40:59      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:技术分享   led   技术   class   deb   ret   exchange   开始   分享图片   

概念: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中的运行结果的三种方式

标签:技术分享   led   技术   class   deb   ret   exchange   开始   分享图片   

原文地址:https://www.cnblogs.com/c-supreme/p/8909058.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!