使用任务并行库(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;
}
}
}
总结
- TaskContinuationOptions.ExecuteSynchronously设置为同步执行,可以实现当前续任务完成后设置在主线程中执行后续任务,在主线程中运行比在线程池中快;
- TaskContinuationOptions.AttachedToParent把子任务添加到父任务,只有所有子任务都完成,父任务才能完成。
备注:学习《Multithreading in C# 5.0 Cookbook》Eugene Agafonov著的总结,以备日后查询。