捕捉在任务中抛出的异常

本文关键字:异常 任务 | 更新日期: 2023-09-27 18:07:14

我试图在我创建的Task中捕获异常,但它们从未"冒泡"到Task运行的地方,它们总是被Visual Studio捕获为运行时错误。

这是我创建的一个SSCCE来显示这个问题

using System;
using System.Threading.Tasks;
namespace ConsoleApplicationSandbox
{
    class Program
    {
        static void Main(string[] args)
        {
            CreateTheIssue();
            Console.ReadLine();
        }
        public static async void CreateTheIssue()
        {
            try
            {
                int val = await ExceptionThrowerClass.DoSomething();
            }
            catch(Exception ex)
            {
                Console.Out.WriteLine("Exception of type " + ex.GetType() + " caught, message: " + ex.Message);
            }
        }
    }
    public static class ExceptionThrowerClass
    {
        public static Task<int> DoSomething()
        {
            return Task.Run(() =>
            {
                throw new FooException("How exceptional!");
                return 1;
            });
        }
    }
    public class FooException : Exception
    {
        public FooException() : base () { }
        public FooException(String message) : base(message) { }
        public FooException(String message, Exception inner) : base (message, inner) { }
    }
}

Visual Studio通知我,当我抛出FooExcepionDoSomething,异常没有被捕获。从这个SO答案和这个MSDN页面,我认为异常只会"冒泡"到myTask.Wait(),随后被捕获。尽管事实似乎并非如此。

这个SCCEE的项目设置是针对。net 4.5.2,我使用的是Visual Studio 2015。我的目标。net框架不能以这种方式捕获异常吗?如何在Main内的try/catch块中捕获FooException ?

编辑:我已经改变了SSCCE使用async/await模式而不是Task.Wait

捕捉在任务中抛出的异常

点击Continue按钮,您将看到异常确实在外部try/catch中被捕获。因为异常进入了Task的内部,所以异常被认为是"User unhand",但是Task通过将任务置于Faulted状态来为您处理它。当您await.Wait()执行任务时,将会重新引发异常。

在编辑之前使用原始方法

    try
    {
        myTask.Wait();
    }
    catch(AggregateException ex)
    {
        var innerException = ex.InnerException;
        Console.Out.WriteLine("Exception of type " + innerException .GetType() + " caught, message: " + innerException.Message);
    }

因为Task会将异常封装到AggregateException中,所以当您使用await时,它会为您打开异常。