异步编程之Task

xiaoxiao2021-02-28  42

概念

Task是一个管理并行工作单元的轻量对象,相当于ThreadPool。处于命名空间System.Threading.Tasks下。

使用

创建和执行任务

有两种方式创建,一种是调用Task.Run(),另一种是使用Task.Factory.StartNew()。 如下示例:

Task t1 = Task.Run(() => { Console.WriteLine("第一个任务"); }); Task t2 = Task.Factory.StartNew(() => { Console.WriteLine("第二个任务"); }); 等待一个或多个任务完成

无条件等待任务完成:使用Task.Wait()等待一个任务完成,调用改方法会一直阻塞线程,直到该任务完成。

Task t1 = Task.Run(() => { Thread.Sleep(500); Console.WriteLine("第一个任务"); }); Console.WriteLine($"t1.Status:{t1.Status}"); // t1.Status:WaitingToRun t1.Wait(); //无条件等待t1完成 Console.WriteLine($"t1.Status:{t1.Status}"); // t1.Status:RanToCompletion

有条件等待任务完成:使用Task.Wait(Int32)或者Task.Wait(TimeSpan)阻塞线程,等待任务完成或者时间间隔结束。

Task t1 = Task.Run(() => { Thread.Sleep(500); Console.WriteLine("第一个任务"); }); Console.WriteLine($"t1.Status:{t1.Status}"); t1.Wait(100); bool completed = t1.IsCompleted; Console.WriteLine($"t1 completed:{completed},t1.Status:{t1.Status}"); if (!completed) { Console.WriteLine("t1任务完成前时间已结束"); } //output: //t1.Status:WaitingToRun //t1 completed:False,t1.Status:Running //t1任务完成前时间已结束 取消任务

使用CancelationToken取消令牌可以对Task做取消操作

static void Main(string[] args) { CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); CancellationToken cancellationToken = cancellationTokenSource.Token; Task t1 = Task.Run(() => { Thread.Sleep(1000); Console.WriteLine("第一个任务"); }); Task t2 = Task.Factory.StartNew(() => { Thread.Sleep(500); RunMethod(cancellationToken); Console.WriteLine("第二个任务"); },cancellationToken); //Thread.Sleep(2000) cancellationTokenSource.Cancel(); Task.WaitAll(t1, t2); } private static void RunMethod(CancellationToken cancellationToken) { Console.WriteLine("进入 取消任务的测试方法"); cancellationToken.ThrowIfCancellationRequested(); Console.WriteLine("结束 取消任务的测试方法"); } //output: // 进入 取消任务的测试方法 // 第一个任务 //如果Thread.Sleep(2000): // 进入 取消任务的测试方法 // 结束 取消任务的测试方法 // 第二个任务 // 第一个任务 异常处理

基本异常处理:

Task t1 = Task.Run(() => { Console.WriteLine("第一个任务"); }); Task t2 = Task.Factory.StartNew(() => { Console.WriteLine("第二个任务"); }); Task t3 = Task.Run(() => { throw new DivideByZeroException(); }); try { Task.WaitAll(t1, t2, t3); } catch (AggregateException ex) { foreach (var inner in ex.InnerExceptions) { Console.WriteLine(inner.Message); } }

使用迭代的异常处理Handler: 当我们需要哪些异常需要处理,哪些异常需要向上传递,System.AggregateException提供了一个Handle()方法来处理AggregateException中的每一个异常,返回true,则表示异常已处理,不用抛出,返回false,抛出异常

Task t1 = Task.Run(() => { Console.WriteLine("第一个任务"); }); Task t2 = Task.Factory.StartNew(() => { Console.WriteLine("第二个任务"); }); Task t3 = Task.Run(() => { throw new DivideByZeroException(); }); try { Task.WaitAll(t1, t2, t3); } catch (AggregateException ex) { ex.Handle((inner) => { if (inner is OperationCanceledException) { return true; } else { return false; } }); }

源码:

https://github.com/zhaobingwang/Demo/tree/master/TaskDemo

参考

MSDN:Task 博客园-吾爱易逝:.Net4.0 任务(Task) .NET 并行(多核)编程系列之五 Task执行和异常处理

转载请注明原文地址: https://www.6miu.com/read-2622087.html

最新回复(0)