C#中的异步多线程4 取消异步、异常处理
一、取消异步执行
可以在异步方法中允许请求终止执行。
class MyClass { public async Task RunAsync(CancellationToken ct) { if (ct.IsCancellationRequested) return; await Task.Run(() => CycleMethod(ct), ct); } void CycleMethod(CancellationToken ct) { Console.WriteLine("Starting CycleMethod"); const int max = 5; for(int i=0;i<max;i++) { if (ct.IsCancellationRequested) return; Thread.Sleep(1000); Console.WriteLine("{0} of {1} iterations completed", i + 1, max); } } } class Program { static void Main(string[] args) { CancellationTokenSource cts = new CancellationTokenSource(); CancellationToken ct = cts.Token; MyClass mc = new MyClass(); Task t = mc.RunAsync(ct); //Thread.Sleep(3000); //cts.Cancel(); t.Wait(); Console.WriteLine("was cancelled:{0}", ct.IsCancellationRequested); Console.ReadLine(); } }
如果注释掉Main中2句,输出如下:
Starting CycleMethod
1 of 5 iterations completed
2 of 5 iterations completed
3 of 5 iterations completed
4 of 5 iterations completed
5 of 5 iterations completed
was cancelled:False
如果不注释,则为:
Starting CycleMethod
1 of 5 iterations completed
2 of 5 iterations completed
3 of 5 iterations completed
was cancelled:True
CancellationToken和CancellationTokenSource被设计用来实现请求终止执行。
1、CancellationToken对象包含一个任务是否应该被取消的信息,拥有CancellationToken对象的任务需要定期检查其token状态。如果CancellationToken对象的IsCancellationRequested属性为true,则任务需停止执行其操作并返回。CancellationToken是不可逆的,并且只能使用一次,一旦IsCancellationRequested属性被设置为true,就不能更改。
2、CancellationTokenSource对象创建可分配给不同任务的CancellationToken对象。任何持有CancellationTokenSource的对象都可以调用其Cancel方法,这回将IsCancellationRequested设置为true。
二、异常处理
static async Task BadAsync() { try { await Task.Run(() => { throw new Exception(); }); } catch { Console.WriteLine("exception in async method"); } } static void Main(string[] args) { Task t = BadAsync(); t.Wait(); Console.WriteLine("Task Status:{0}", t.Status); Console.WriteLine("Task IsFaulted:{0}", t.IsFaulted); }
尽管可以使用try catch抛出exception,但最后Task的状态仍然为RanToCompletion,原因是Task没有被取消,也没有未处理的异常。