处理异步异常

时间:2019-04-08 09:37:52

标签: c# .net exception async-await

我想知道如何让此代码落入catch的{​​{1}}中?

PassThrough

fiddle

外部代码应返回处理错误路径并返回using System; using System.Threading.Tasks; public class Program { public static async Task Main(string[] args) { try { await PassThrough(Test()); } catch (Exception) { Console.WriteLine("caught at invocation"); } Console.ReadLine(); } public static async Task PassThrough(Task<bool> test) { try { var result = await test.ConfigureAwait(false); // still need to do something with result here... } catch { Console.WriteLine("never caught... :("); } } /// external code! public static Task<bool> Test() { throw new Exception("something bad"); // do other async stuff here // ... return Task.FromResult(true); } }
通过Task.FromException吗?

3 个答案:

答案 0 :(得分:2)

我的建议是将您的PassThrough方法更改为采用Func<Task<bool>>而不是Task<bool>。这样,您可以捕获由Test方法的同步部分及其启动的异步任务引起的异常。另一个优势是,异步方法(使用asyncawait定义的方法可以直接转换为Func<Task>Func<Task<TResult>>

using System;
using System.Threading.Tasks;

public class Program
{
    public static async Task Main()
    {
        try
        {
            await PassThrough(Test);   
            // Note that we are now passing in a function delegate for Test,
            // equivalent to () => Test(), not its result.
        } 
        catch (Exception) 
        {
            Console.WriteLine("caught at invocation");
        }

        Console.ReadLine();
    }

    public static async Task PassThrough(Func<Task<bool>> test)
    {
        try
        {
            var task = test();   // exception thrown here
            var result = await task.ConfigureAwait(false);

            // still need to do something with result here...
        }
        catch
        {
            Console.WriteLine("caught in PassThrough");
        }
    }

    /// external code!
    public static Task<bool> Test()
    {
        throw new Exception("something bad");

        // do other async stuff here
        // ...

        return Task.FromResult(true);
    }
}

答案 1 :(得分:1)

添加到Douglas的答案中。

仅当您能够对异常进行有意义的处理并且可以在该级别进行管理时,才捕获异常。

Task.FromException基本上只是将异常放在通常要返回的任务上。但是,在这种情况下,异步等待模式已经为您完成了此操作。即,如果您只是让它失败,那么无论如何都会将异常放置在任务上,因此您的代码似乎没有真正的理由来捕获任何东西。

您必须考虑捕获异常的唯一相关位置是在async void中,因为它们不会被观察到,并且在引发异常时会引起问题

答案 2 :(得分:0)

在下面的行中,您正在等待PassThrough,而不是Test

await PassThrough(Test());

如果需要,您可以同时等待两者:

await PassThrough(await Test()); // also need to change the signature of PassThrough from Task<bool> to bool.

...但是在两种情况下,都将首先调用Test。并且由于它引发了异常,因此PassThrough将永远不会被调用。这就是您看不到“通行卡住” 消息的原因。执行过程永远不会输入此方法。