簡體   English   中英

未捕獲異步方法中的異常

[英]Exception in async methods is not caught

以下代碼無法捕獲我通過調用ct.ThrowIfCancellationRequested引發的ct.ThrowIfCancellationRequested

public partial class TitleWindow : Window, IAsyncInitialization
{
    public Task Initialization{get; private set;}
    CancellationTokenSource cts;

    public TitleWindow()
    {
        InitializeComponent();
        cts = new CancellationTokenSource();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        try
        {
            cts.Cancel();
            Initialization = GetCancelExceptionAsync(cts.Token);
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("Operation canceled!");
        }
    }

    public async Task GetCancelExceptionAsync(CancellationToken ct)
    {
        await Task.Delay(1000);
        ct.ThrowIfCancellationRequested();
    }
}

但是,如果我用以下代碼替換Window_Loaded方法(使其異步並等待異步方法的調用),則會捕獲異常。

private async void Window_Loaded(object sender, RoutedEventArgs e)
{
    try
    {
        cts.Cancel();
        await GetCancelExceptionAsync(cts.Token);
    }
    catch (OperationCanceledException)
    {
        Console.WriteLine("Operation canceled!");
    }
}

為什么我的第一種方法不起作用? 異常是否沒有正確傳播到正確的同步上下文?

我試圖使用Stephen Clearys博客文章中描述The Asynchronous Initialization Pattern ,以便稍后等待在構造函數中啟動的任務(並且為了使其與第二個示例具有可比性,我使用了( asyncWindow_Loaded事件馬上等待那里的方法,例如上一個問題中向我建議的方法)。 然后,我想提供一個取消在構造函數中啟動的異步方法的選項,由於異常處理無法按預期工作,因此我目前仍停留在該方法中。

使用我的“非工作”代碼,我可以通過在某個地方的try-catch塊中放置一個“ await Initialization ”來捕獲該異常,但是我仍然會收到一個額外的未處理異常。

如何以一種允許我以后等待異步方法的方式實現此方法(以確保我不會處理對象的不一致狀態),並且仍然能夠取消該長時間運行的Task(當然,需要返回/設置默認值)?

在第一個示例中,未捕獲到異常,因為在離開try/catch塊之前不會發生該異常。 如果要在那里捕獲它,則需要像在第二個示例中那樣完全在這里等待/ await 如果您不等待返回的任務,該方法將繼續執行並在實際發生異常之前離開try/catch塊。

如果要“帶外”捕獲異常,還可以注冊TaskScheduler.UnobservedTaskException (如果任務拋出了一個未捕獲的異常,則調用此事件)以獲取所有未捕獲的異常或監視task Exception屬性。 也可以查看答案。

Exeption被拋出另一個線程中的任務。

public async Task GetCancelExceptionAsync(CancellationToken ct)
        {
            try
            {
                await Task.Delay(1000);
                ct.ThrowIfCancellationRequested();
            }
            catch (Exception e)
            {
                // your Cancleation expeption
            }
        }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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