使用任务并行库(3)

使用任务执行基本的操作

简介

设置相互依赖的任务,展示节省短暂任务的线程开销的方法。

以下是代码实践:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace 组合任务
{
    internal class Program
    {
        private static void Main()
        {
            var firstTask = new Task<int>(() => TaskMethod("First Task", 3));
            var secondTask = new Task<int>(() => TaskMethod("Second Task", 2));

            //给第一个任务设置后续操作,在第一个任务完成后执行
            firstTask.ContinueWith(t => Console.WriteLine("The first answer is {0}. Thread id {1}, " +
                                                          "is thread pool thread: {2}",
                                                          t.Result, Thread.CurrentThread.ManagedThreadId,
                                                          Thread.CurrentThread.IsThreadPoolThread));

            firstTask.Start();
             secondTask.Start();

             Thread.Sleep(TimeSpan.FromSeconds(4));//等待上面两个任务的完成

            /* 设置第二个任务的后续操作,TaskContinuationOptions.ExecuteSynchronously设置为同步执行,
             * 如果上面不等待4秒,后续曹操将放到线程池中等待第二个任务执行完成后执行;如果等待4秒,即等待
             * 第二个任务的完成,则后续操作被放到主线程中执行。因为后续操作非常短暂,所以放到主线程中比放到
             * 线程池中运行快。
             * TaskContinuationOptions.OnlyOnRanToCompletion指示第二个任务完成后才会安排后续任务。
             */
            var continuation = secondTask.ContinueWith(t => Console.WriteLine("The second answer is {0}. Thread id {1}, " +
                                                               "is thread pool thread: {2}",
                                                          t.Result, Thread.CurrentThread.ManagedThreadId,
                                                          Thread.CurrentThread.IsThreadPoolThread),
                                                          TaskContinuationOptions.OnlyOnRanToCompletion |
                                                          TaskContinuationOptions.ExecuteSynchronously);

            //给continuation任务继续安排后续任务
            continuation.GetAwaiter().OnCompleted(
                () => Console.WriteLine("Continuation Task Completed!" +
                                      " Thread id {0}, is thread pool thread: {1}", Thread.CurrentThread.ManagedThreadId,
                                      Thread.CurrentThread.IsThreadPoolThread));

            Thread.Sleep(TimeSpan.FromSeconds(2));
            Console.WriteLine();


            /* 子任务必须在父任务运行时创建,并且正确的附加给父任务!
             * TaskContinuationOptions.AttachedToParent把子任务添加到父任务,只有所有子任务都完成,父任务才能完成。
             */
            firstTask = new Task<int>(() =>
            {
                //创建firstTask的子任务
                var innerTask = Task.Factory.StartNew(() => TaskMethod("Second Task", 5), TaskCreationOptions.AttachedToParent);
                //创建firstTask的子任务,为创建innerTask的延续任务。
                innerTask.ContinueWith(t => TaskMethod("Third Task", 2), TaskContinuationOptions.AttachedToParent);
                return TaskMethod("First Task", 2);
            });

            firstTask.Start();

            //验证父任务是否在子任务全部结束后完成
            while (!firstTask.IsCompleted)
            {
                Console.WriteLine(firstTask.Status);
                Thread.Sleep(TimeSpan.FromSeconds(0.5));
            }
            Console.WriteLine(firstTask.Status);

            Thread.Sleep(TimeSpan.FromSeconds(10));

            Console.ReadKey();
        }

        private static int TaskMethod(string name, int seconds)
        {
            Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
            Thread.Sleep(TimeSpan.FromSeconds(seconds));
            return 42 * seconds;
        }
    }
}

总结

  1. TaskContinuationOptions.ExecuteSynchronously设置为同步执行,可以实现当前续任务完成后设置在主线程中执行后续任务,在主线程中运行比在线程池中快;
  2. TaskContinuationOptions.AttachedToParent把子任务添加到父任务,只有所有子任务都完成,父任务才能完成。

备注:学习《Multithreading in C# 5.0 Cookbook》Eugene Agafonov著的总结,以备日后查询。

posted on 2017-09-23 09:55  五月槐花  阅读(66)  评论(0编辑  收藏  举报

导航