Task,异步,多线程简单总结
1,如何把一个异步封装为Task异步
Task.Factory.FromAsync
对老的一些异步模型封装为Task
TaskCompletionSource
更通用,在回调中只要SetResult()一下就表示Task结束了,用它可以将各种异步回调封装为Task
2,一个可以await的可以返回Task的Async结尾的异步方法从哪里开始进入另一个线程的
如果是对BeginXXX EndXXX的APM异步模型封装的,从进入XXXAsync方法后直到BeginXXX前还在调用方法的线程内,然后无阻塞的等待回调,当等打完后,就相当于在回调中了,此时可能进入了另一个线程,其他也是类似的,从底层方法异步的地方开始异步的,而不是一进入方法就到了另一个线程了,所以进入方法后写很多CPU密集程序是会阻塞的
3,如何立刻扔到另一个线程
Task.Run或者Task.Factory.StartNew可以直接从另一个线程开始,可以直接把XXXAsync方法扔进去
4,一个约定
纯C#框架或者类库提供的Async结尾的可await方法,里面一定有无阻塞异步的实现,否则没必要搞成异步的,就比如newtonsoft.json的异步序列化方法被标识为已过时。
5,Task外面如何告诉Task该取消了
CancellationTokenSource
其实和一个Flag差不多,只不过封装了一些方法以异常类
6,很多情况下要先学会同步才能并发
7,Task.Run Task.Start Task.Factory.StartNew 等都是使用线程池的线程
8,IO异步底层为IRP消息,通常是和硬件交互所使用的消息机制,当然那是驱动层的事情,IO异步当然也就是无阻塞的,等IRP消息回来就是回调
9,UI线程
最终会渲染界面的代码一定要在UI线程执行,可以使用比如winform的control.Invoke ,wpf的Dispatcher , 还有利用SynchronizationContext
10,异常处理
var checkT1 = Task.Run(async () => { throw new Exception("1"); throw new Exception("2"); }); try { await checkT1; } catch (AggregateException ex) { ex.Flatten(); foreach (var item in ex.InnerExceptions) { MessageBox.Show("show1:" + item.Message); } } catch (Exception ex2) { MessageBox.Show("show2:" + ex2.Message); }
var checkT1 = Task.Run(() => { throw new Exception("1"); throw new Exception("2"); }); try { await checkT1; } catch (AggregateException ex) { ex.Flatten(); foreach (var item in ex.InnerExceptions) { MessageBox.Show("show1:" + item.Message); } } catch (Exception ex2) { MessageBox.Show("show2:" + ex2.Message); }
以上两种,输出 show2:1,也就是立即抛出原来的异常,在等待时可捕获
var checkT1 = Task.Run(async () => { throw new Exception("1"); throw new Exception("2"); }); try { checkT1.Wait(); } catch (AggregateException ex) { ex.Flatten(); foreach (var item in ex.InnerExceptions) { MessageBox.Show("show1:" + item.Message); } } catch (Exception ex2) { MessageBox.Show("show2:" + ex2.Message); } var checkT1 = Task.Run(() => { throw new Exception("1"); throw new Exception("2"); }); try { checkT1.Wait(); } catch (AggregateException ex) { ex.Flatten(); foreach (var item in ex.InnerExceptions) { MessageBox.Show("show1:" + item.Message); } } catch (Exception ex2) { MessageBox.Show("show2:" + ex2.Message); }
以上两种 Show1:1 ,也就是进入AggregateException异常处理
var checkT1 = Task.Factory.StartNew(async () => { throw new Exception("1"); throw new Exception("2"); });
会吞掉异常
此时需要用GetAwaiter
12:各种同步类,并发类
待补充
一旦开始并发了,还有很多很多的坑