Task:
Task是.Net 提供了基于任务的异步模式,它不是线程,但是运行在线程池的线程上。
Task(任务)是架构在线程之上的,最终还是让线程去执行。
Task(任务)类似于ThreadPool功能,用Task开启新任务时,会从线程池中调用线程。但是任务比线程池有更小的开销和精确的控制
Task的创建:
1.直接创建:
Task t = new Task(() =>
{
Console.WriteLine("任务开始工作……");
//模拟工作过程
Thread.Sleep(5000);
});
t.Start();
t.ContinueWith((task) =>
{
Console.WriteLine("任务完成,完成时候的状态为:");
Console.WriteLine("IsCanceled={0}\tIsCompleted={1}\tIsFaulted={2}", task.IsCanceled, task.IsCompleted, task.IsFaulted);
});
Console.ReadKey();
结果:
2.工厂创建
Task.Factory.StartNew(()={
});
3.Task.Run
Task.Run(()=>{
});
4.以上都是无返回值的创建,本次是有返回值的创建
//Task<TResult > 就是有返回值的Task, TResult 就是返回类型
//例1:
var tcs = new TaskCompletionSource<int>();
new Thread(() => {
Thread.Sleep(5000);
int i = Enumerable.Range(1, 100).Sum();
tcs.SetResult(i); }).Start();//线程把运行计算结果,设为tcs的Result。
Task<int> task = tcs.Task;
Console.WriteLine(task.Result); //此处会阻塞,直到匿名线程调用tcs.SetResult(i)完毕
//例2:
//返回值类型为string
Task<string> task = Task<string>.Run(() => {
Thread.Sleep(2000);
return Thread.CurrentThread.ManagedThreadId.ToString();
});
//会等到task执行完毕才会输出;
Console.WriteLine(task.Result);
通过task.Result可以取到返回值,若取值的时候,后台线程还没执行完,则会等待其执行完毕!
总结下实例:
//直接创建
var t1 = new Task(() => TaskMethod("Task 1"));
var t2 = new Task(() => TaskMethod("Task 2"));
t2.Start();
t1.Start();
Task.WaitAll(t1, t2); //等待所有任务都执行完
Task.Run(() => TaskMethod("Task 3")); //Task.Run(...)
Task.Factory.StartNew(() => TaskMethod("Task 4")); //工厂创建
//标记为长时间运行任务,则任务不会使用线程池,而在单独的线程中运行。
Task.Factory.StartNew(() => TaskMethod("Task 5"), TaskCreationOptions.LongRunning);
//启动任务,并安排到当前任务队列线程中执行任务(System.Threading.Tasks.TaskScheduler)
task.Start();
Console.WriteLine("主线程执行其他处理");
task.Wait();
Thread.Sleep(TimeSpan.FromSeconds(1));
static void 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);
}
执行结果:
Task的任务控制
方法名 | 说明 |
---|---|
Task.Wait | taskT.Wait()就是等taskT任务执行完毕,taskT的状态变为Completed |
Task.WaitAll | Task.WaitAll(task,task2,task3…N) 等所有…任务执行完毕在继续往下执行 |
Task.WaitAny | Task.WaitAny(task,task2,task3…N) 任意一个任务完成就继续往下执行 |
Task.ContinueWith | taskT.ContinueWith(task=>{…}) 等待前一个taskT执行完毕在执行 括号里内容 |
CancellationTokenSource | 通过cancellation的tokens来取消一个Task。 |
前三个好理解,主要提一下后边两个:
Task.ContinueWith
根据上一个任务Task执行情况执行下一个 任务Task 或者是别的什么东西
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();
var result = task1.ContinueWith<string>(task =>
{
Console.WriteLine("task1执行成功后task2开始");
task2.Start();
return "测试带返回参数";
}, TaskContinuationOptions.OnlyOnRanToCompletion);
Console.WriteLine(result.Result.ToString());
Console.ReadLine();
执行结果:
Task的取消 CancellationTokenSource
应用场景:任务异常时,或者时按钮取消等。
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();
Console.ReadLine();
执行结果:
参考:https://blog.csdn.net/younghaiqing/article/details/81455410
实例汇总: