https://blog.csdn.net/younghaiqing/article/details/81455410php
Task 类的表示单个操做不返回一个值,一般以异步方式执行。 Task 对象是一个的中心思想 基于任务的异步模式 首次引入.NET Framework 4 中。 由于由执行工做 Task 对象一般以异步方式执行在线程池线程上而不是以同步方式在主应用程序线程,您可使用 Status 属性,以及 IsCanceled, ,IsCompleted, ,和 IsFaulted 属性,以肯定任务的状态。 大多数状况下,lambda 表达式用于指定的任务是执行的工做。编程
对于返回值的操做,您使用 Task 类。markdown
任务Task和线程Thread的区别:多线程
一、任务是架构在线程之上的,也就是说任务最终仍是要抛给线程去执行。架构
二、任务跟线程不是一对一的关系,好比开10个任务并非说会开10个线程,这一点任务有点相似线程池,可是任务相比线程池有很小的开销和精确的控制。异步
Task和Thread同样,位于System.Threading命名空间下!函数
Task 类还提供了构造函数对任务进行初始化,但的未计划的执行。 出于性能缘由, Task.Run 或 TaskFactory.StartNew(工厂建立) 方法是用于建立和计划计算的任务的首选的机制,但对于建立和计划必须分开的方案,您可使用的构造函数(new一个出来),而后调用 Task.Start 方法来计划任务,以在稍后某个时间执行。性能
//第一种建立方式,直接实例化:必须手动去Start var task1 = new Task(() => { //TODO you code }); task1.Start(); //第二种建立方式,工厂建立,直接执行 var task2 = Task.Factory.StartNew(() => { //TODO you code });
方法名 | 说明 |
---|---|
Created | 表示默认初始化任务,可是“工厂建立的”实例直接跳过。 |
WaitingToRun | 这种状态表示等待任务调度器分配线程给任务执行。 |
RanToCompletion | 任务执行完毕。 |
//查看Task中的状态 var task1 = new Task(() => { Console.WriteLine("Begin"); System.Threading.Thread.Sleep(2000); Console.WriteLine("Finish"); }); Console.WriteLine("Before start:" + task1.Status); task1.Start(); Console.WriteLine("After start:" + task1.Status); task1.Wait(); Console.WriteLine("After Finish:" + task1.Status); Console.Read();
方法名 | 说明 |
---|---|
Task.Wait | task1.Wait();就是等待任务执行(task1)完成,task1的状态变为Completed。 |
Task.WaitAll | 待全部的任务都执行完成: |
Task.WaitAny | 发同Task.WaitAll,就是等待任何一个任务完成就继续向下执行 |
Task.ContinueWith | 第一个Task完成后自动启动下一个Task,实现Task的延续 |
CancellationTokenSource | 经过cancellation的tokens来取消一个Task。 |
下面详细介绍一下上面的几个方法:spa
task1.Wait();就是等待任务执行(task1)完成,task1的状态变为Completed。
看字面意思就知道,就是等待全部的任务都执行完成:
{
Task.WaitAll(task,task2,task3...N) Console.WriteLine("All task finished!"); }
即当task,task2,task3…N所有任务都执行完成以后才会往下执行代码(打印出:“All task finished!”)
这个用发同Task.WaitAll,就是等待任何一个任务完成就继续向下执行,将上面的代码WaitAll替换为WaitAny
{
Task.WaitAny(task,task2,task3...N) Console.WriteLine("Any task finished!"); }
即当task,task2,task3…N任意一个任务都执行完成以后就会往下执行代码(打印出:” Any task finished!”)
就是在第一个Task完成后自动启动下一个Task,实现Task的延续,下面咱们来看下他的用法,编写以下代码:
static void Main(string[] args) { var task1 = new Task(() => { Console.WriteLine("Task 1 Begin"); System.Threading.Thread.Sleep(2000); Console.WriteLine("Task 1 Finish"); }); var task2 = new Task(() => { Console.WriteLine("Task 2 Begin"); System.Threading.Thread.Sleep(3000); Console.WriteLine("Task 2 Finish"); }); task1.Start(); task2.Start(); var result = task1.ContinueWith<string>(task => { Console.WriteLine("task1 finished!"); return "This is task result!"; }); Console.WriteLine(result.Result.ToString()); Console.Read(); }
能够看到,task1完成以后,开始执行后面的内容,而且这里咱们取得task的返回值。
前面说了那么多Task的用法,下面来讲下Task的取消,好比咱们启动了一个task,出现异常或者用户点击取消等等,咱们能够取消这个任务。如何取消一个Task呢,咱们经过cancellation的tokens来取消一个Task。在不少Task的Body里面包含循环,咱们能够在轮询的时候判断IsCancellationRequested属性是否为True,若是是True的话就return或者抛出异常,抛出异常后面再说,由于尚未说异常处理的东西。
下面在代码中看下如何实现任务的取消,代码以下:
var tokenSource = new CancellationTokenSource(); var token = tokenSource.Token; var task = Task.Factory.StartNew(() => { for (var i = 0; i < 1000; i++) { System.Threading.Thread.Sleep(1000); if (token.IsCancellationRequested) { Console.WriteLine("Abort mission success!"); return; } } }, token); token.Register(() => { Console.WriteLine("Canceled"); }); Console.WriteLine("Press enter to cancel task..."); Console.ReadKey(); tokenSource.Cancel();
这里开启了一个Task,并给token注册了一个方法,输出一条信息,而后执行ReadKey开始等待用户输入,用户点击回车后,执行tokenSource.Cancel方法,取消任务。
参考文献:
1.http://www.javashuo.com/article/p-cpizczev-bb.html
2.https://msdn.microsoft.com/zh-cn/library/system.threading.tasks.task.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1
using System; using System.Threading.Tasks; using System.Threading; namespace 实现取消选项 { class Program { static void Main(string[] args) { var cts = new CancellationTokenSource(); var longTask = new Task<int>(() => TaskMethod("Task 1", 10, cts.Token), cts.Token); Console.WriteLine(longTask.Status); cts.Cancel(); Console.WriteLine(longTask.Status); Console.WriteLine("First task has been cancelled before execution"); cts = new CancellationTokenSource(); longTask = new Task<int>(() => TaskMethod("Task 2", 10, cts.Token), cts.Token); longTask.Start(); for (int i = 0; i < 5; i++) { Thread.Sleep(TimeSpan.FromSeconds(0.5)); Console.WriteLine(longTask.Status); } cts.Cancel(); for (int i = 0; i < 5; i++) { Thread.Sleep(TimeSpan.FromSeconds(0.5)); Console.WriteLine(longTask.Status); } Console.WriteLine("A task has been completed with result {0}.", longTask.Result); Console.ReadKey(); } private static int TaskMethod(string name,int seconds,CancellationToken token) { Console.WriteLine("Task {0} is running on a thread id {1},Is thread pool thread: {2}", name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); for (int i = 0; i < seconds; i++) { Thread.Sleep(TimeSpan.FromSeconds(1)); if (token.IsCancellationRequested) { Console.WriteLine("Cancel Task {0} is running on a thread id {1},Is thread pool thread: {2}", name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); return -1; } } return 42 * seconds; } } }