c# - 异步方法异常的不同行为

标签 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();
}

现在,如果您在这 2 个方法上await,行为将几乎相同。但是,如果您正在执行任务,则行为会有所不同。

如果我想缓存这种计算的结果,但仅当任务运行完成时才缓存。 我必须处理两种情况:

第一种情况:

public Task<TResult> CachingThis1(Func<Task<TResult>> doSomthing1)
{
    try
    {
       var futur = doSomthing1()
       futur.ContinueWith(
               t =>
               {
                  // ... Add To my cache
               },
               TaskContinuationOptions.NotOnFaulted);
    }
    catch  ()
    {
        // ... Remove from the pending cache
        throw;
    }
}

第二种情况

public Task<TResult> CachingThis2(Func<Task<TResult>> doSomthing)
{
    var futur = SomeMethod2();
    futur.ContinueWith(
       t =>
       {
           // ... Add To my cache
       },
       TaskContinuationOptions.NotOnFaulted);
    futur.ContinueWith(
       t =>
       {
          // ... Remove from the pending cache
       },
       TaskContinuationOptions.OnlyOnFaulted);
}

现在我将执行缓存计算的方法传递给我的缓存系统。

cachingSystem.CachingThis1(SomeMethod1);
cachingSystem.CachingThis2(SomeMethod2);

很明显,我需要在“ConinueWith on faulted”和 catch block 中复制代码。 您知道是否有办法使异常在等待之前或之后表现相同?

最佳答案

SomeMethod1SomeMethod2 所需的异常处理没有区别。它们的运行方式完全相同,异常将存储在返回的任务中。

这在这个例子中很容易看出;

static void Main(string[] args)
{
    try
    {
        var task = SomeMethod1();
    }
    catch
    {
        // Unreachable code
    }
}

public static async Task SomeMethod1()
{
    throw new Exception();
}

在这种情况下不会处理任何异常,因为没有等待返回的任务。

然而,简单的 Task 返回方法和 async 方法之间存在区别:

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< 中等待返回的任务 block :

public static async Task HandleAsync()
{
    try
    {
        await TaskReturning();
        // Add to cache.
    }
    catch
    {
        // handle exception from both the synchronous and asynchronous parts.
    }
}

关于c# - 异步方法异常的不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27106532/

相关文章:

c# - 辅助功能自动化属性 "Name"是否需要本地化?

go - 为什么 Go 除了错误处理之外还要添加 panic 和恢复?

c++ - 在给定 _EXCEPTION_POINTERS 结构的情况下,如何获取导致结构化异常的模块名称? (win32 C++)

java - java中使用assert和抛AssetionError异常的区别

c# - 在字符串中动态插入换行符

c# - 从 VS2017 附加到 docker 内正在运行的进程

c# - 从 LDAP 查询用户组

.net - ASP.NET MVC Web 应用程序中的 Controller 是否应该调用存储库、服务或两者?

.net - 是否可以在外部 javascript 文件中插入我的尖括号、百分比、等于 <%= %> 语法?

c# - 读取 .NET Core 2.0 库中的配置设置