C# 异步方法异常的不同行为

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块中复

假设您有2个
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
    }
}