重新抛出异常的任务(TPL)失去堆栈跟踪堆栈、抛出、异常、任务

由网友(揪绒绒)分享简介:我有code,它重新抛出异常。 当我后来读到异常的task.Exception,它的堆栈跟踪点的地方,我的位置重新抛出异常(N线,而不是直线m,如我所料)。为什么会这样呢?错误的TPL或者更可能的东西我都忽略了。当我解决方法我可以包装异常的内异常的新异常。内部类节目{私有静态无效的主要(字串[] args){Task...

我有code,它重新抛出异常。

当我后来读到异常的task.Exception,它的堆栈跟踪点的地方,我的位置重新抛出异常(N线,而不是直线m,如我所料)。

为什么会这样呢?错误的TPL或者更可能的东西我都忽略了。

当我解决方法我可以包装异常的内异常的新异常。

 内部类节目
{
    私有静态无效的主要(字串[] args)
    {
        Task.Factory.StartNew(TaskMethod).ContinueWith(T => Console.WriteLine(t.Exception.InnerException));
        Console.Read();
    }

    私有静态无效TaskMethod()
    {
        尝试
        {
行M:抛出新的异常(待办事项);
        }
        赶上(例外)
        {
线N:扔;
        }
    }
}
 

解决方案

不幸的是,由于第三方物流的方式存储的异常,直到任务执行完毕,原来的堆栈跟踪丢失。运行您的样品code在LINQPad显示,异常被抛出在在System.Threading.Tasks.Task.Execute(),这显然是不正确的。

由于原油的解决方法,你的可以的存储原始的堆栈跟踪(它是一个简单的字符串)的原始异常的数据属性,你就可以访问它,那么:

 私有静态无效TaskMethod()
{
    尝试
    {
        抛出新的异常(待办事项);
    }
    赶上(例外前)
    {
        ex.Data [OriginalStackTrace] = ex.StackTrace;
        扔;
    }
}
 
java中如何抛出异常使程序不中断 7

那么你就必须存储在数据词典的 OriginalStackTrace 值的原始堆栈跟踪:

这不是你真正想要的,但我希望它能帮助。

I've code that rethrows an exception.

When I later read the exception from task.Exception, its stacktrace points to the location where I re-threw the exception (line n and not line m, as I expected).

Why is this so? bug in TPL or more likely something I have overlooked.

As I workaround I can wrap the exception as the inner-exception in a new exception.

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;
        }
    }
}

解决方案

Unfortunately, due to the way TPL stores exceptions until the task finished executing, the original stack trace is lost. Running your sample code in LINQPad shows that the exception was thrown at at System.Threading.Tasks.Task.Execute(), which is obviously not correct.

As a crude workaround, you could store the original stack trace (it being a simple string) on the Data property of the original exception, and you'll be able to access it then:

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

Then you'll have the original stack trace stored in the OriginalStackTrace value of the Data dictionary:

It's not really what you want, but I hope it helps.

阅读全文

相关推荐

最新文章