繁体   English   中英

C#async / await未观察到的异常

[英]C# async / await unobserved exception

我试图理解为什么以下代码:

async void Handle_Clicked(object sender, System.EventArgs e)
{
    try
    {
        await CrashAsync("aaa");
    }
    catch (Exception exception)
    {
        Log($"observed exception");

        Log($"Exception: {exception.Message}");
    }
}

private async Task CrashAsync(string title)
{
    Log($"CrashAsync ({title}) - before");

    await Task.Delay(1000);

    throw new Exception($"CrashAsync ({title})");

    Log($"CrashAsync ({title}) - after");
}

产生预期的结果:

线程#1:CrashAsync(aaa) - 之前

线程#1:观察到异常

线程#1:例外:CrashAsync(aaa)

但如果我把它改成这个:

async void Handle_Clicked(object sender, System.EventArgs e)
{
    try
    {
        await CrashAsync("aaa").ContinueWith(async (t) =>
        {                   
            await CrashAsync("bbb");
        },TaskContinuationOptions.OnlyOnRanToCompletion);
    }
    catch (Exception exception)
    {
        Log($"observed exception");

        Log($"Exception: {exception.Message}");
    }
}

我得到以下输出:

线程#1:CrashAsync(aaa) - 之前

线程#1:观察到异常

线程#1:异常:任务被取消。

线程#2:未观察到的异常

线程#2:System.Exception:位于/Users/johndoe/Development/Xamarin/AsyncTest/AsyncTest/AsyncTestPage.xaml.cs:82中AsyncTest.AsyncTestPage + c__async3.MoveNext()[0x000ad]的CrashAsync(aaa)

哪里:

TaskScheduler.UnobservedTaskException += (sender, e) =>
{
    Debug.WriteLine($"thread #{Environment.CurrentManagedThreadId}: unobserved exception");

    foreach (var exception in e.Exception.Flatten().InnerExceptions)
    {
        Debug.WriteLine($"thread #{Environment.CurrentManagedThreadId}: {exception}");
    }
};

不满足延续条件,因此ContinueWith任务被取消,但为什么我有未观察到的异常?

您等待ContinueWith返回的Task ,因此您观察到与此Task相关的异常 - 它被取消( TaskCanceledException )。 但是你没有观察到CrashAsync抛出的原始异常(所以“CrashAsync aaa”)异常,因此你观察到的行为。

以下是获取更多理解的示例代码:

static async void Test() {
    var originalTask = CrashAsync("aaa");
    var onSuccess = originalTask.ContinueWith(async (t) =>
    {
        await CrashAsync("bbb");
    }, TaskContinuationOptions.OnlyOnRanToCompletion);
    var onFault = originalTask.ContinueWith(t => {                    
        Log("Observed original exception: " + t.Exception.InnerExceptions[0].Message);
    }, TaskContinuationOptions.OnlyOnFaulted);
}

所以简而言之 - 只需等待你的任务并捕获异常(如果有的话)。 你根本不需要使用ContinueWith ,因为如果你使用await - 方法的其余部分已经是一个延续。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM