我有以下代码:

    public async Task AsyncMethod()
    {
        await Task.Factory.StartNew(() =>
        {
            throw new Exception();
        });
    }

    public ActionResult Index()
    {
        var t1 = Task.Factory.StartNew(() => { throw new Exception(); });
        var t2 = Task.Factory.StartNew(() => { throw new Exception();});
        var t3 = Task.Factory.StartNew(async () => { await AsyncMethod(); });

        try
        {
            Task.WaitAll(t1, t2, t3);
        }
        catch (AggregateException ex)
        {
            var count1 = ex.InnerExceptions.Count;
            var count2 = ex.Flatten().InnerExceptions.Count;

            throw;
        }

        return View();
    }


我想了解为什么count1和count2变量是2而不是3,如何在AsyncMethod中获取第三个异常?

最佳答案

我想了解为什么count1和count2变量是2而不是3,如何在AsyncMethod中获取第三个异常?


Task.Factory.StartNew返回基本的Task。如果将其传递给async委托,则返回的Task仅表示async方法的开始(直到它产生给调用方的点为止)。

您应该将Task.Runasync代码一起使用。 Task.Run将为Task委托创建一个async包装器,因此从Task返回的Task.Run表示整个async方法。

Stephen Toub具有an excellent blog post detailing the differences between Task.Run and Task.Factory.StartNew

另外,如usr所述,每当在GUI或ASP.NET上下文中阻塞Task而不是await时,死锁都会出现问题。我有a blog post that goes into detail about this deadlock problem。您应该使用await Task.WhenAll而不是Task.WaitAll

因此,这是同时应用了两个更改的代码:

public async Task AsyncMethod()
{
    await Task.Run(() =>
    {
        throw new Exception();
    });
}

public async Task<ActionResult> Index()
{
    var t1 = Task.Run(() => { throw new Exception(); });
    var t2 = Task.Run(() => { throw new Exception();});
    var t3 = Task.Run(async () => { await AsyncMethod(); });

    try
    {
        await Task.WhenAll(t1, t2, t3);
    }
    catch (Exception)
    {
        var ex1 = t1.Exception.InnerException;
        var ex2 = t2.Exception.InnerException;
        var ex3 = t3.Exception.InnerException;

        throw;
    }

    return View();
}

关于c# - 在异步委托(delegate)中捕获异常,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14102135/

10-11 19:29
查看更多