[英]General approach to handle Task cancellation correctly
我正在進行代碼審查,並且我擔心這種模式,貫穿所有代碼:
try
{
await DoSomethingAsync();
await DoSomethingElseAsync();
// and so on...
}
catch (OperationCanceledException)
{
// all good, user cancelled
// log and return
return;
}
// handle other particular exceptions
// ...
catch (Exception ex)
{
// fatal error, alert the user
FatalErrorMessage(ex);
}
我關心的部分是處理OperationCanceledException
。 這段代碼不應該也處理AggregateException
並檢查唯一的內部異常是否是OperationCanceledException
?
我知道Task.Wait
或Task.Result
會拋出類似的AggregateException
,而不是OperationCanceledException
。 代碼的作者向我保證她只使用async/await
out out並且從不使用Wait/Result
。 因此,她不喜歡另外觀察AggregateException
進行取消的想法。 但是,我的觀點是一些標准的基於Task
的BCL API仍然可以使用AggregateException
包裝OperationCanceledException
,例如因為它們仍然可能在內部訪問Task.Result
。
是否有意義? 我們是否應該擔心處理OperationCanceledException
和AggregateException
以正確觀察取消?
但是,我的觀點是一些標准的基於任務的BCL API仍然可以使用AggregateException包裝OperationCanceledException,例如因為它們仍然可能在內部訪問Task.Result。
不,他們不會這樣做。
我們應該擔心同時處理OperationCanceledException和AggregateException以正確觀察取消嗎?
我會說不。 這是當然, 可能是一個AggregateException
可以包含OperationCanceledException
,但它也可以包含other particular exceptions
一樣容易。
只要您遵循異步最佳實踐(即,沒有異步同步或同步異步),您就不必擔心這一點。
嗯,這絕對是技術上可行的,這個代碼很容易驗證:
static void Main()
{
Test().Wait();
}
static async Task Test()
{
try
{
await ThrowAggregate();
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
static async Task ThrowAggregate()
{
ThrowException().Wait();
}
static async Task ThrowException()
{
throw new OperationCanceledException();
}
ThrowAggregate
將AggregateException存儲在返回的任務內,因此等待它仍會引發AggregateException
。 因此,如果您想勤奮工作,那么也需要捕獲AggregateException
。
但是,BCL中的任何方法都不太可能這樣做,如果它確實存在比異常處理更大的問題,因為您執行異步過度同步。 我會更擔心你自己的代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.