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:各種同步類,並發類
待補充
一旦開始並發了,還有很多很多的坑