为什么ContinueWhenAll隐藏未观察到的异常

时间:2015-02-20 13:02:20

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

当我调用ContinueWhenAll(...)时,任务中未观察到的异常被完全隐藏。不会引发UnobservedTaskException事件,也不会杀死应用程序。我等了几个小时。 我当然放下以下

<runtime>
    <ThrowUnobservedTaskExceptions enabled="true"/>
</runtime>

进入配置文件。

如果我发表评论ContinueWhenAll,则会引发事件并且应用程序很快被杀死。此外,简单的延续ContinueWith也不会隐藏未被观察到的异常。

static void Main(string[] args)
{
    TaskScheduler.UnobservedTaskException += (s, e) =>
        {
            Console.WriteLine("From unobserved exception handler: {0}", e.Exception.Message);
        };

    var faultedTask = Task.Factory.StartNew(() => { throw new Exception("Task is faulted"); });

    // 1. ContinueWhenAll hides unobserved exception
    Task.Factory.ContinueWhenAll(new Task[] { faultedTask }, ts =>
    {
        Console.WriteLine("From \"when all\" continuation");
    });

    // 2. Simple continuation does not hide unobserved exception
    //faultedTask.ContinueWith(t => { Console.WriteLine("From \"simple\" continuation"); });

    faultedTask = null;
    int gcCounter = 0;
    while (true)
    {
        // artifical memory consumption
        int[][] a = new int[4096][];
        for (int j = 0; j < 4096; j++ )
            a[j] = new int[4096];

        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();

        Console.WriteLine("Garbage collected: {0}", ++gcCounter);
        Thread.Sleep(500);
    }
}

1 个答案:

答案 0 :(得分:1)

您的测试存在问题。即使使用UnobservedTaskException,我也无法获得Task.ContinueWith但是当我将任务解压缩到不同的方法时,会在Task.ContinueWith 上引发事件。 Task.Factory.ContinueWhenAll(正如Sriram Sakthivel指出的那样,在发布模式下构建也会产生相同的效果):

static void Main()
{
    TaskScheduler.UnobservedTaskException += (s, e) =>
    {
        Console.WriteLine("From unobserved exception handler: {0}", e.Exception.Message);
    };

    RunTask();

    int gcCounter = 0;
    while (true)
    {
        // artifical memory consumption
        int[][] a = new int[4096][];
        for (int j = 0; j < 4096; j++)
            a[j] = new int[4096];

        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();

        Console.WriteLine("Garbage collected: {0}", ++gcCounter);
        Thread.Sleep(500);
    }
}

static void RunTask()
{
    var faultedTask = Task.Factory.StartNew(() => { throw new Exception("Task is faulted"); });

    // 1. ContinueWhenAll hides unobserved exception
    Task.Factory.ContinueWhenAll(new[] { faultedTask }, ts =>
    {
        Console.WriteLine("From \"when all\" continuation");
    });

    // 2. Simple continuation does not hide unobserved exception
    //faultedTask.ContinueWith(t => { Console.WriteLine("From \"simple\" continuation"); });
}

所以,你没有得到这个例外的原因只是Task还没有GC。