C# - 抛出异常但调用方方法已经完成的任务会发生什么情况?
C# - What happens to a Task that throws an exception but the caller method is already done?
如果满足以下 if
语句,并且 Bar()
抛出异常,会发生什么(以及为什么)?
async Task Foo()
{
Task<object> myTask = Bar();
if (condition)
{
return;
}
else
{
await myTask;
// ....
return;
}
}
异常会被捕获吗?由谁?
不,不会捕获异常。您需要专门向 Task
添加一个延续(请注意,当您 await
一个任务时,您正在向它添加一个延续)。
如果Bar
抛出一个异常,它会在你调用它的地方被抛出。
但是,如果 Bar
returns 的 Task
包装异常,发生的情况取决于您的 .NET 运行时版本 - 对于 .NET 4.0,它会降低您的整个过程,因为它最终导致在终结器线程(或线程池线程)上抛出异常。对于 .NET 4.5+,异常将被静默处理。
反正你也不要。您应该 always 显式处理任何可以在异步任务中传播的异步异常。如果您不想 await
代码的某个分支中的任务(例如,您正在预加载您 认为 需要的数据,但不要t), 至少在任务上绑定一个延续,以优雅地处理任何可能的异常。
如果满足以下 if
语句,并且 Bar()
抛出异常,会发生什么(以及为什么)?
async Task Foo()
{
Task<object> myTask = Bar();
if (condition)
{
return;
}
else
{
await myTask;
// ....
return;
}
}
异常会被捕获吗?由谁?
不,不会捕获异常。您需要专门向 Task
添加一个延续(请注意,当您 await
一个任务时,您正在向它添加一个延续)。
如果Bar
抛出一个异常,它会在你调用它的地方被抛出。
但是,如果 Bar
returns 的 Task
包装异常,发生的情况取决于您的 .NET 运行时版本 - 对于 .NET 4.0,它会降低您的整个过程,因为它最终导致在终结器线程(或线程池线程)上抛出异常。对于 .NET 4.5+,异常将被静默处理。
反正你也不要。您应该 always 显式处理任何可以在异步任务中传播的异步异常。如果您不想 await
代码的某个分支中的任务(例如,您正在预加载您 认为 需要的数据,但不要t), 至少在任务上绑定一个延续,以优雅地处理任何可能的异常。