C#异步/等待未观察到的异常 [英] C# async / await unobserved exception
问题描述
我试图理解为什么下面的代码:
I'm trying to understand why the following code:
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)-之前
thread #1: CrashAsync (aaa) - before
线程1:观察到的异常
线程#1:例外:CrashAsync(aaa)
thread #1: Exception: CrashAsync (aaa)
但是如果我将其更改为此:
but if I change it to this one:
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)-之前
thread #1: CrashAsync (aaa) - before
线程1:观察到的异常
线程#1:异常:任务已取消.
thread #1: Exception: A task was canceled.
线程2:无法观察到的异常
thread #2: unobserved exception
线程#2:System.Exception:CrashAsync(aaa) 在/Users/johndoe/Development/Xamarin/AsyncTest/AsyncTest/AsyncTestPage.xaml.cs:82
thread #2: System.Exception: CrashAsync (aaa) at AsyncTest.AsyncTestPage+c__async3.MoveNext () [0x000ad] in /Users/johndoe/Development/Xamarin/AsyncTest/AsyncTest/AsyncTestPage.xaml.cs:82
其中:
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任务,但是为什么我有未观察到的异常?
The continuation condition is not satisfied so the ContinueWith task is cancelled, but why do I have unobserved exception?
推荐答案
您正在等待ContinueWith
返回的Task
,因此您观察到与此Task
相关的异常-已将其取消(TaskCanceledException
).但是,您不会观察到CrashAsync引发的原始异常(即"CrashAsync aaa")异常,因此不会观察到您的行为.
You await Task
returned by ContinueWith
, so you observe exception related to this Task
- that it was cancelled (TaskCanceledException
). But you don't observe original exception thrown by CrashAsync (so "CrashAsync aaa") exception, hence the behavior you observe.
下面是示例代码,可以帮助您进一步理解:
Here is sample code to get more understanding:
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,则该方法的其余部分已经已经了.
So in short - just await your task and catch exception if any. You don't need to use ContinueWith
at all, because if you use await - the rest of the method is already a continuation.
这篇关于C#异步/等待未观察到的异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!