Task是.NetFramework3.0出現的,線程是基於線程池,然后提供了豐富的API
TaskFactory 提供對創建和計划 Task 對象的支持
創建和啟動異步任務
1、Task task = new Task(() => ThreadPoolHelper.DoSomeThing());
task.Start();
2、Task task = Task.Run(() => ThreadPoolHelper.DoSomeThing());
3、TaskFactory taskFactory = Task.Factory;
Task task = taskFactory.StartNew(() => ThreadPoolHelper.DoSomeThing());
Task的線程是源於線程池 ,假如說我想控制下Task的並發數量,該怎么做?

1 { 2 //ThreadPool.SetMaxThreads(8, 8); 3 //線程池是單例的,全局唯一的 4 //設置后,同時並發的Task只有8個;而且線程是復用的; 5 //全局的,請不要這樣設置!!! 6 for (int i = 0; i < 100; i++) 7 { 8 int k = i; 9 Task.Run(() => 10 { 11 Console.WriteLine($"This is k={k},i={i} running ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}"); 12 Thread.Sleep(2000); 13 }); 14 } 15 }
運行上面的代碼我們發現幾個需要注意的地方:
1、i的值等於100,因為異步線程的啟動並不阻塞主線程;
2、使用ThreadPool.SetMaxThreads 方法 設置后,雖然能達到效果,但是線程池是單例的,全局唯一的,這樣設置會影響整個程序;
那么如何實現?

1 { 2 List<Task> taskList = new List<Task>(); 3 for (int i = 0; i < 10000; i++) 4 { 5 int k = i; 6 if (taskList.Count(t => t.Status != TaskStatus.RanToCompletion) >= 20) 7 { 8 Task.WaitAny(taskList.ToArray()); 9 taskList = taskList.Where(t => t.Status != TaskStatus.RanToCompletion).ToList(); 10 } 11 taskList.Add(Task.Run(() => 12 { 13 Console.WriteLine($"This is {k} running ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}"); 14 Thread.Sleep(2000); 15 })); 16 } 17 }
使用Parallel也可以實現
Task常用方法
1、Delay(Int32)、Delay(Int32, CancellationToken)、Delay(TimeSpan)、Delay(TimeSpan, CancellationToken)
在指定的時間后執行任務

1 { 2 Stopwatch stopwatch = new Stopwatch(); 3 stopwatch.Start(); 4 Console.WriteLine("在Delay之前"); 5 Task.Delay(2000).ContinueWith(t => { Console.WriteLine($"Delay耗時ContinueWith Start{stopwatch.ElapsedMilliseconds}"); ThreadPoolHelper.DoSomeThing(); Console.WriteLine($"Delay耗時ContinueWith End{stopwatch.ElapsedMilliseconds}"); }); 6 Console.WriteLine($"Delay耗時{stopwatch.ElapsedMilliseconds}"); 7 }
2、ContinueWith(Action<Task,Object>, Object)、ContinueWith(Action<Task>)、ContinueWith<TResult>(Func<Task,Object,TResult>, Object, CancellationToken, TaskContinuationOptions, TaskScheduler)、...
目標任務完成后異步執行一個延續任務
3、Wait()、Wait(CancellationToken)、Wait(Int32)、Wait(Int32, CancellationToken)、Wait(TimeSpan)
等待任務或經過指定時間為止 與Thread.Join方法、waitHandle.WaitOne方法 作用相當
4、WaitAll(Task[])、WaitAll(Task[], CancellationToken)、WaitAll(Task[], Int32)、WaitAll(Task[], Int32, CancellationToken)、WaitAll(Task[], TimeSpan)
等待所有任務對象完成執行或經過指定時間為止,或等到取消等待
5、WaitAny(Task[])、WaitAny(Task[], CancellationToken)、WaitAny(Task[], Int32)、WaitAny(Task[], Int32, CancellationToken)、WaitAny(Task[], TimeSpan)
等待所有任務對象任何一個任務對象完成執行或經過指定時間為止,或等到取消標記取消
6、WhenAll(IEnumerable<Task>)、WhenAll(Task[])、WhenAll<TResult>(IEnumerable<Task<TResult>>)、WhenAll<TResult>(Task<TResult>[])
所有任務對象都已完成時,創建一個新的任務並執行
7、WhenAny(IEnumerable<Task>)、WhenAny(Task[])、WhenAny<TResult>(IEnumerable<Task<TResult>>)、WhenAny<TResult>(Task<TResult>[])
所有任務對象任何一個任務完成就創建一個新的任務並執行
TaskFactory常用方法
1、ContinueWhenAll(Task[], Action<Task[]>)、ContinueWhenAll(Task[], Action<Task[]>, CancellationToken)、ContinueWhenAll(Task[], Action<Task[]>, CancellationToken, TaskContinuationOptions, TaskScheduler)、...
所有任務對象都已完成時,創建一個新的任務並執行 與Task.WhenAll方法 作用相當
2、ContinueWhenAny(Task[], Action<Task>)、ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[], Action<Task<TAntecedentResult>>)、...
所有任務對象任何一個任務完成就創建一個新的任務並執行 與Task.WhenAny方法 作用相當
微軟文檔:
Task:https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.tasks.task?view=netframework-4.8
TaskFactory:https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.tasks.taskfactory?view=netframework-4.8