在任务中重新抛出异常(TPL)会丢失堆栈跟踪

时间:2011-09-27 13:53:17

标签: c# .net task task-parallel-library

我的代码重新抛出异常。

当我稍后从task.Exception读取异常时,它的stacktrace指向我重新抛出异常的位置(行n而不是行m,正如我预期的那样)。

为什么会这样? TPL中的错误或更可能是我忽略的内容。

当我解决方法时,我可以将异常包装为新异常中的内部异常。

internal class Program
{
    private static void Main(string[] args)
    {
        Task.Factory.StartNew(TaskMethod).ContinueWith(t => Console.WriteLine(t.Exception.InnerException));
        Console.Read();
    }

    private static void TaskMethod()
    {
        try
        {
line m:     throw new Exception("Todo");
        }
        catch (Exception)
        {
line n:     throw;
        }
    }
}

1 个答案:

答案 0 :(得分:3)

不幸的是,由于TPL在任务完成执行之前存储异常的方式,原始堆栈跟踪将丢失。在LINQPad中运行示例代码表明在at System.Threading.Tasks.Task.Execute()抛出了异常,这显然是不正确的。

作为一种粗略的解决方法,您可以在原始异常的Data属性上存储原始堆栈跟踪(它是一个简单的字符串),您将能够访问然后:

private static void TaskMethod()
{
    try
    {           
        throw new Exception("Todo");
    }
    catch (Exception ex)
    {
        ex.Data["OriginalStackTrace"] = ex.StackTrace;
        throw;
    }
}

然后,您将原始堆栈跟踪存储在OriginalStackTrace字典的Data值中:

这不是你想要的,但我希望它有所帮助。