Try-Catch Async Exceptions

时间:2011-06-16 19:02:04

标签: c# exception async-await c#-5.0

此示例“失败”:

static async void Main(string[] args)
{
    try
    {
        await TaskEx.Run(() => { throw new Exception("failure"); });
    }
    catch (Exception)
    {
        throw new Exception("success");
    }
}

也就是说,文本“失败”的异常会冒泡。

然后我尝试了这个解决方法:

static async void Main(string[] args)
{
    try
    {
        await SafeRun(() => { throw new Exception("failure"); });
    }
    catch (Exception)
    {
        throw new Exception("success");
    }
}

static async Task SafeRun(Action action)
{
    var ex = default(Exception);
    await TaskEx.Run(() =>
    {
        try
        {
            action();
        }
        catch (Exception _)
        {
            ex = _;
        }
    });
    if (ex != default(Exception))
        throw ex;
}

这也没有帮助。

我想我的Async CTP刷新安装可能已经过了。

这段代码应该像我期望的那样工作(“成功”起泡,而不是“失败”),或者这不是“假设”以这种方式工作。如果没有,你会如何解决它?

1 个答案:

答案 0 :(得分:5)

您看到的行为可能是边缘案例错误,甚至可能是正确的,如果不直观的话。通常,当您同步调用异步方法时,它会执行一个任务来执行,因为没有人等待任务完成,所以异常永远不会进入主线程。如果你直接调用Main会成功,但是你的运行时会在另一个线程上看到“成功”的例外。

由于main是应用程序的入口点,因此它会被同步调用,并且可能因为入口点不会触发Task包装行为,因此await不能正常运行并且TaskEx.Run会抛出自己的线程,在运行时显示为在另一个线程上抛出的异常。

如果你以async方法运行main,即返回Task(因为返回async的{​​{1}}只能通过{{1}真正调用从同步主上下文中阻塞它,你会得到适当的行为,如下面的测试所示:

void

即。任务以await错误,其中包含成功异常,因为它是内部异常。