C# 异步方法异常的不同行为
假设您有2个C# 异步方法异常的不同行为,c#,.net,exception-handling,task-parallel-library,async-await,C#,.net,Exception Handling,Task Parallel Library,Async Await,假设您有2个async方法,定义如下: public async Task<TResult> SomeMethod1() { throw new Exception(); } public async Task<TResult> SomeMethod2() { await Task.Delay(50); throw new Exception(); } 第二种情况 显然,我需要在“ConinueWithon faulted”和catch块中复
async
方法,定义如下:
public async Task<TResult> SomeMethod1()
{
throw new Exception();
}
public async Task<TResult> SomeMethod2()
{
await Task.Delay(50);
throw new Exception();
}
第二种情况
显然,我需要在“ConinueWith
on faulted”和catch块中复制代码。
您知道是否有方法使异常在等待之前或之后的行为相同吗?对于
SomeMethod1
和SomeMethod2
而言,所需的异常处理没有区别。它们的运行方式完全相同,异常将存储在返回的任务中
在这个例子中很容易看出这一点
static void Main(string[] args)
{
try
{
var task = SomeMethod1();
}
catch
{
// Unreachable code
}
}
public static async Task SomeMethod1()
{
throw new Exception();
}
在这种情况下不会处理任何异常,因为不会等待返回的任务
然而,简单的任务
返回方法和异步
方法之间存在区别:
public static Task TaskReturning()
{
throw new Exception();
return Task.Delay(1000);
}
public static async Task Async()
{
throw new Exception();
await Task.Delay(1000);
}
您可以通过简单地使用一个async
包装器方法来避免代码重复,该方法在单个try-catch
块中调用该方法并wait
s返回的任务:
public static async Task HandleAsync()
{
try
{
await TaskReturning();
// Add to cache.
}
catch
{
// handle exception from both the synchronous and asynchronous parts.
}
}
除了I3arnon在回答中所说的之外,如果您在异步方法上使用
ContinueWith
on而没有指定的TaskContinuationOptions
,那么您在continuation处理程序中收到的Task
参数捕获的异常可以通过以下方式处理:
SomeMethod1().ContinueWith(ProcessResult);
SomeMethod2().ContinueWith(ProcessResult);
使用ProcessResult
处理程序,该处理程序如下所示:
private void ProcessResult<TResult>(Task<TResult> task)
{
if (task.IsFaulted)
{
//remove from cahe
}
else if (task.IsCompleted)
{
//add to cache
}
}
private void ProcessResult(任务)
{
if(task.IsFaulted)
{
//从cahe移除
}
else if(任务已完成)
{
//添加到缓存
}
}
如果我没有错,您的catch块将永远不会执行,因为异步方法的异常传播是不同的。您一定是对的,但我的示例遗漏了一些我忽略的重要内容。查看我的编辑
public static async Task HandleAsync()
{
try
{
await TaskReturning();
// Add to cache.
}
catch
{
// handle exception from both the synchronous and asynchronous parts.
}
}
SomeMethod1().ContinueWith(ProcessResult);
SomeMethod2().ContinueWith(ProcessResult);
private void ProcessResult<TResult>(Task<TResult> task)
{
if (task.IsFaulted)
{
//remove from cahe
}
else if (task.IsCompleted)
{
//add to cache
}
}