首页 新闻 会员 周边

TaskScheduler.UnobservedTaskException观察未处理的异常疑问

0
悬赏园豆:40 [已解决问题] 解决于 2013-04-14 11:40

书上说Task中未观察到的异常可在TaskScheduler.UnobservedTaskException事件中SetObserved处理。避免由CLR的终结器捕获该异常重而终止应用程序。。。

问题:我没有这样捕获并SetObserved。而且也确保没有调用过Task的Wait()、Result、Exception成员。但是我的应用程序没有被终止。。。

参考代码:

            TaskScheduler.UnobservedTaskException += (s, e) =>
            {
                //设置所有未觉察异常被觉察
                //e.SetObserved();
            };

            Task.Factory.StartNew(() =>
            {
                throw new Exception();
            });

            //确保任务完成
            Thread.Sleep(100);
            //强制垃圾会受到
            GC.Collect();
            //等待终结器处理
            GC.WaitForPendingFinalizers();

 

 

求高手解答下。。。

滴答的雨的主页 滴答的雨 | 老鸟四级 | 园豆:3660
提问于:2013-04-13 22:37
< >
分享
最佳答案
0

答案已经找到:http://www.cnblogs.com/TianFang/archive/2012/12/24/2831341.html

 

TPL中的未处理异常

由于async函数和TPL存在非常大的关联,在分析async函数异常处理方式前,首先来复习下TPL中对于异常是如何处理的,以如下代码为例:

    static void Main(string[] args)
    {
        TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
        Test();

        Console.ReadLine();        //
等待
Test任务执行完成

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

        Console.ReadLine();
    }

    static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
    {
        Console.WriteLine(e.Exception);
    }

    public static Task Test()
    {
        return Task.Run(() => { throw new Exception(); });
    }

执行上面代码后,我们可以发现:

  1. Test任务抛异常后,程序能仍然能正常运行
  2. GC执行时,可以通过TaskScheduler.UnobservedTaskException捕获到Test任务抛异常的信息。

从上面代码执行结果,我们可以大致了解Tpl对未处理异常的处理方式:

  1. Task未处理异常不会继续往上抛导致程序异常终止
  2. Task中未处理异常可以通过TaskScheduler.UnobservedTaskException事件捕获
  3. TaskScheduler.UnobservedTaskException事件并不是在抛异常时立即的,而是GC时从Finalizer线程里触发并执行的。

简单的说,TaskScheduler中处理了Task中抛出的异常,不会导致程序异常终止。老赵的Blog关于C#中async/await中的异常处理中详细描述了这一过程,感兴趣的朋友可以看看。

不过,Task中的未处理异常不会导致程序异常终止在另一方面也掩盖了代码中存在bug的隐患,因此建议注册TaskScheduler.UnobservedTaskException事件,对未处理异常记录日志,方便后续跟踪分析。

滴答的雨 | 老鸟四级 |园豆:3660 | 2013-04-14 11:36
其他回答(1)
0
TaskScheduler.UnobservedTaskException += (s, e) =>
            {
                //设置所有未觉察异常被觉察
                //e.SetObserved();
            };
应该是进入这段代码,异常就到此为止了
收获园豆:40
chenping2008 | 园豆:9836 (大侠五级) | 2013-04-14 09:26

木有,未有这段代码也会终止这个异常。我 天方  一个博文中找到答案了。

支持(0) 反对(0) 滴答的雨 | 园豆:3660 (老鸟四级) | 2013-04-14 11:35

@滴答的雨: 请问楼主,未有这段代码 也没有终止的原因是什么呀?望赐教

支持(0) 反对(0) 麻将我会 | 园豆:24 (初学一级) | 2016-02-26 13:44
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册