簡體   English   中英

正確處理任務取消的一般方法

[英]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.WaitTask.Result會拋出類似的AggregateException ,而不是OperationCanceledException 代碼的作者向我保證她只使用async/await out out並且從不使用Wait/Result 因此,她不喜歡另外觀察AggregateException進行取消的想法。 但是,我的觀點是一些標准的基於Task的BCL API仍然可以使用AggregateException包裝OperationCanceledException ,例如因為它們仍然可能在內部訪問Task.Result

是否有意義? 我們是否應該擔心處理OperationCanceledExceptionAggregateException以正確觀察取消?

但是,我的觀點是一些標准的基於任務的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM