近来在学习Eugene Agafonov编写的《C#多线程编程实战》(译),做些笔记也顺便分享一下^-^
任务(Task)是什么?首先我们先了解一个概念, .Net Framework4.0引入了一个新的关于异步操作的API,叫任务并行库(Task Parallel Library,简称TPL),在.Net Framework4.5版,对该API进行了轻微的改进,使用更简单。TPL可被认为是线程池之上的又一个抽象层,其对程序员隐藏了与线程池交互的底层代码,并提供了更方便的细粒度的API。
而TPL的核心概念就是任务(Task),一个任务代表了一个异步操作,该操作可以通过多种方式运行,可以使用或不使用独立显存运行,一个任务还可以通过多种方式和其他任务组合起来,光说不练假把式,让我们一起看着例子来学习Task任务的用法吧。
using System; using System.Threading.Tasks; using System.Threading; namespace 使用任务执行基本的操作 { class Program { static void Main(string[] args) { TaskMethod("Main Thread Task"); Task task = CreateTask("Task 1"); task.Start(); int result = task.Result; Console.WriteLine("Result is: {0}", result); task = CreateTask("Task 2"); task.RunSynchronously(); result = task.Result; Console.WriteLine("Result is: {0}", result); task = CreateTask("Task 3"); task.Start(); while (!task.IsCompleted) { Console.WriteLine(task.Status); Thread.Sleep(TimeSpan.FromSeconds(0.5)); } Console.WriteLine(task.Status); result = task.Result; Console.WriteLine("Result is: {0}", result); Console.ReadKey(); } static TaskCreateTask(string name) { return new Task(() => TaskMethod(name)); } static int TaskMethod(string name) { 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(2)); return 42; } } }
程序运行结果如下:
首先直接运行TaskMethod方法,这里并没有把它封装到一个任务中。结果根据它提供给我们的主线程的信息可以得知该方法是被同步执行的。很显然它不是线程池中的线程。
然后我们运行了Task 1,使用Start方法启动该任务并等待结果。该任务会被放置在线程池中,并且主线程会等待,直到任务返回前一直处于阻塞状态。
Task 2和Task 1类似,除了Task 2是通过RunSynchronously()方法运行的。该任务会运行在主线程中,该任务的输出与第一个例子中直接同步调用TakMethod的输出完全一样。这是个非常好的优化,可以避免使用线程池来执行非常短暂的操作。
我们用以运行Task 1相同的方式来运行Task 3。但这次没有阻塞主线程,只是在该任务完成前循环打印出任务状态。结果展示了多种任务状态,分别是Creatd、Running和RanToCompletion。