之前看ET框架的時候,發現了一些不理解的地方。其實都是集中在async-await的用法和TaskCompleteSource的用法上的,這會兒就學習了一些。
第一個例子:
然後在Main函數中調用TaskCompleteSourceButton_OnClick方法,
TaskCompleteSourceButton_OnClick();
Console.WriteLine("等待中!!!!");
Console.ReadKey();
運行後,會發現,主線程處於阻塞的情況,後面的“等待中!!!”要等到異步任務完成後纔會輸出。
話說,使用async-await不是應該是異步操作的嗎?爲什麼主線程還會阻塞呢?
再來看第二個例子:
這個例子在運行的時候,就不會發生阻塞了:
這兩個例子,一個使用了TaskCompleteSource,一個沒有使用。這有關係,卻不是真正的原因,真正的原因:第一個例子的代碼,通過TaskCompleteSource類,在主線程中獲取了異步任務的運行結果,所以會造成阻塞。最簡單的測試方法就是去掉TaskCompleteSource類,在運行的時候,就會發現主線程沒有阻塞了。修改如下:
如此後,主線程就不會阻塞了。但是如果去掉while循環中的註釋的話,那麼在輸出“等待結果中!!!”後,就會直接阻塞線程。原因是一樣的,因爲這裏獲取了異步任務的返回結果,所以會發生阻塞。
說到這裏,就要說一說TaskCompleteSource的作用了,咋一看,用不用這個類,都能獲取異步任務的記過,也都阻塞了線程,有啥區別呢?區別就在於,這個類其實是一個回調方法,任務結束後,調用這個回調可以傳遞很多任務運行的數據,包括運行結果。所以我們可以獲取該回調的來做一些事情。在貓大的給出的例子《更好的協程》中,將TaskCompleteSource對象拋出去,在一個while循環中獲取到該對象,從而解析出任務運行的結果。這樣就不會阻塞線程了,同時也可以實時獲取到異步任務的結果,符合大家對異步編程的需求。