TaskScheduler.UnobservedTaskException从不被调用 [英] TaskScheduler.UnobservedTaskException never gets called

查看:184
本文介绍了TaskScheduler.UnobservedTaskException从不被调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据我的研究,我学到了以下内容:

Based on my research, I have learned the following:


  1. TaskScheduler.UnobservedTaskException 必须等待任务被垃圾收集,然后该任务的不可观察的异常才会冒泡到 UnobservedTaskException 事件。

  2. 如果你'使用 Task.Wait(),它永远不会被调用,因为你阻止了即将到来的任务结果,因此异常将被抛出 Task.Wait()而不是泡到 UnobservedException 事件。

  3. 调用 GC.Collect()手动通常是一个坏主意,除非你确切知道你在做什么,因此在这种情况下,确认事情是好的,但不是

  1. TaskScheduler.UnobservedTaskException must wait for the task to be garbage collected before that task's unobserved exception will bubble up to the UnobservedTaskException event.
  2. If you're using Task.Wait(), it'll never get called anyway, because you're blocking on an impending result from the Task, hence the exception will be thrown on Task.Wait() rather than bubble up to the UnobservedException event.
  3. Calling GC.Collect() manually is generally a bad idea unless you know exactly what you're doing, hence it's good in this case for confirming things, but not as a proper solution to the issue.

问题

如果我的应用程序在垃圾收集器启动之前退出,我绝对100%无法获取我的 UnobservedTaskExceptio

If my application exits before the garbage collector kicks in, I absolutely 100% cannot get my UnobservedTaskException event to fire.

请注意以下代码:

class Program
{
    static void Main(string[] args)
    {
        TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
        Task.Factory.StartNew(() =>
        {
            Console.WriteLine("Task started.");
            throw new Exception("Test Exception");
        });
        Thread.Sleep(1000);
        //GC.Collect();
        //GC.WaitForPendingFinalizers();
    }

    static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
    {
        File.WriteAllText(@"C:\data\TestException.txt", e.Exception.ToString());
        Console.WriteLine("EXCEPTION UNOBSERVED");
    }
}

没有写入任何异常文件,安慰。 10-15分钟后,应用程序退出后仍然可以继续,仍然没有看到我的应用程序的遗留物被垃圾收集。你可能会问,为什么不只是在出口收集?那么我的现实世界的场景是,我的异常陷阱运行在Windows服务内托管的一个WCF服务中。当Windows服务关闭时,我无法陷阱(因此手动调用 GC.Collect()),因为没有任何事件可以看到。 strong>

No exception file is written and nothing is written to the console. 10-15 minutes and more can go by after the application exits and still I see no evidence that my application's remains were garbage collected. You might ask, well why not just collect on exit? Well, my real world scenario is that my exception trapping runs inside a WCF service hosted inside a Windows service. I cannot trap when the Windows service is shutting down (and hence manually call GC.Collect()) because there is no event for that as far as I can see.

我哪里错了?如何确保如果WCF服务内部的内容最终会破坏我的Windows服务,那么我有机会在服务崩溃之前记录异常?

Where am I going wrong? How do I ensure that if something deep inside the WCF service is going to ultimately break my windows service, that I have a chance to log the exception before the service falls over?

推荐答案

对我来说,TaskScheduler.UnobservedTaskException首先给出了一个非常错误的安全感。如果它取决于垃圾收集,这真的不值得。

To me, TaskScheduler.UnobservedTaskException at first gives a very wrong sense of security. It's really not worth much if it depends on Garbage Collection.

我发现以下解决方案取自这个msdn文章,要更加可靠。只有在task1中存在未处理的异常,并且不会阻止UI执行时,它基本上会执行继续块(您记录异常)。

I found the following solution, taken from this msdn article, to be much more reliable. It basically executes the continuation block (where you log the exception) only if there were unhandled exceptions in task1, and does not block UI execution.

您可能还想平展嵌套的聚合异议,也许创建一个扩展方法,如这里描绘的Reed Copsey

You might also want to flatten nested AggregateExceptions and perhaps create a extension method, as Reed Copsey depicted here.

var task1 = Task.Factory.StartNew(() =>
{
    throw new MyCustomException("Task1 faulted.");
})
.ContinueWith((t) =>
{
    Console.WriteLine("I have observed a {0}",
        t.Exception.InnerException.GetType().Name);
},
TaskContinuationOptions.OnlyOnFaulted);

这篇关于TaskScheduler.UnobservedTaskException从不被调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆