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 ListtaskList = new List (); 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
目标任务完成后异步执行一个延续任务
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
所有任务对象都已完成时,创建一个新的任务并执行
7、WhenAny(IEnumerable
所有任务对象任何一个任务完成就创建一个新的任务并执行
TaskFactory常用方法
1、ContinueWhenAll(Task[], Action
所有任务对象都已完成时,创建一个新的任务并执行 与Task.WhenAll方法 作用相当
2、ContinueWhenAny(Task[], Action
所有任务对象任何一个任务完成就创建一个新的任务并执行 与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