异步编程异常和死锁处理
?
在.NET異步編程中,通常使用async和await這對黃金搭檔,返回類型使用Task或Task<T>。在方法前面加async表示這個方法運行異步,在方法內使用await表示執行一個異步等待。
?
下面是一個簡單例子:
?
static void Main(string[] args) { Doth(); Console.ReadKey(); } static async Task Doth() { int i = 2; await Task.Delay(TimeSpan.FromSeconds(2)); i += 2; await Task.Delay(TimeSpan.FromSeconds(2)); Console.WriteLine(i); }?
當執行DoSth方法,第一個await執行一個異步等待,當執行完成,就繼續執行下面的代碼。在async修飾的方法內部,一個await就是一個異步等待,可以包含多個await, 每一個await執行完畢才會執行它后面的代碼,也就是說在DoSth內部是同步的。
?
各個await在哪個線程中運行呢?
?
默認情況下是在當前線程中運行,不過.NET提供了ConfigureAwait方法,用來設置await在哪個線程中運行。
?
static async Task Doth() { int i = 2; await Task.Delay(TimeSpan.FromSeconds(2)).ConfigureAwait(false); i += 2; await Task.Delay(TimeSpan.FromSeconds(2)).ConfigureAwait(false); Console.WriteLine(i); }?
以上,當第一個await運行在控制臺項目所在的線程中,第二個await將在線程池上運行。
?
我們無法保證每個await不會拋出異常,通常按如下的方式捕獲異常。
?
async Task DosthAsync() { try { await PossibleExceptionAsync(); } catch(NotSuppotedException ex) { LogException(ex); throw; } }?
由于拋出的異常會放在Task對象中,所以也可以這么寫:
?
async Task DosthAsync() { Task task = PossibleExceptionAsync(); try { await task; } cach(NotSupportedException ex) { LogException(ex); throw; } }?
異步編程也會出現死鎖。
?
async Task DoSthSync() { await Task.Delay(TimeSpan.FromSeconds(1)); } void FirstThing() { Task tak = DoSthSync(); task.Wait(); }?
以上,如果調用FirstThing方法就會出現死鎖的情況。
?
→執行FirstThing方法
→在FirstThing方法內部執行DoSthSync方法,這時,當前上下文線程被阻塞
→來到DoSthSync方法中,其中的await試圖捕獲當前上下文線程,而當前的上下線程已經被阻塞在那里了,造成死鎖。
?
死鎖如何解決死鎖呢?
?
可以在DoSthSync內部不使用當前上下文線程,改用線程池中的線程,修改如下:
?
async Task DoSthSync() { await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false); }?
或者,讓FirstThing變成一個異步方法。修改如下:
?
async Task DoSthSync() { await Task.Delay(TimeSpan.FromSeconds(1)); } async Task FirstThing() { await DoSthSync(); }轉載于:https://www.cnblogs.com/darrenji/p/4710425.html
總結
以上是生活随笔為你收集整理的异步编程异常和死锁处理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2019牛客暑期多校训练营(第七场)D
- 下一篇: 粒子编辑器的选择1