• 使用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();
            }
  • 相关阅读:
    C语言I博客作业07
    C语言I博客作业06
    C语言I博客作业05
    C语言I博客作业04
    C语言II博客作业04
    C语言II博客作业03
    C语言II博客作业01
    学期总结
    C语言I博客作业08
    C语言I博客作业07
  • 原文地址:https://www.cnblogs.com/c-supreme/p/8909058.html
Copyright © 2020-2023  润新知