【问题标题】:Using the UnobservedTaskException handler in dotnetcoreapp2.0在 dotnetcoreapp2.0 中使用 UnobservedTaskException 处理程序
【发布时间】:2018-12-21 23:46:22
【问题描述】:

以下代码在 netcoreapp2.0 应用程序中运行时,似乎最终不会抛出 UnobservedTaskException

using System;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp3 {

    class Program {

        public static void Main(string[] args) {

            TaskScheduler.UnobservedTaskException += (s, e) => {
                /// Try to crash the application - we wanna nail unobserved exceptions dead.
                /// Unfortunately, this code never seems to run.
                Console.WriteLine("UnobservedTaskException thrown.");
                throw e.Exception; 
            };

            var t = Task.Run(() => {
                throw new NotImplementedException();
            });

            while (!t.IsFaulted)
                Thread.Sleep(1);

            t = null;
            Console.WriteLine("Task is faulted.");

            GC.Collect();
            GC.WaitForPendingFinalizers();
            Console.ReadKey();
        }

    }
}

这是项目文件。如何让UnobservedTaskException 处理程序被解雇?

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <LangVersion>7.3</LangVersion>
  </PropertyGroup>

</Project>

在其他 stackoverflow 帖子中,我看到了在项目文件中使用以下 sn-p 的建议,但它仅适用于 .net framework 4.0+ 项目。如果有 .netcore 项目文件的等效文件,那可能就是我需要知道的。

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

【问题讨论】:

  • 我不确定这会触发UnobservedTaskException。在此处尝试示例代码:stackoverflow.com/a/3284286/1202807
  • @GabrielLuci 我做到了。 UnobservedTaskException 处理程序未触发

标签: c# .net-core unobserved-exception


【解决方案1】:

我有同样的问题。只需尝试在 RELEASE 模式下运行它。我对其进行了测试,它可以与控制台应用程序 .net 核心版本 2.2 一起使用。

internal class Program
{
    private static void Main(string[] args)
    {
        // REMEMBER TO RUN IN RELEASE MODE

        var handler = new EventHandler<UnobservedTaskExceptionEventArgs>(Unobserved);
        TaskScheduler.UnobservedTaskException += handler;

        Task.Run(() => { Console.WriteLine("task 1"); throw new Exception("TASK 1 EXCEPTION"); });
        Task.Run(() => { Console.WriteLine("task 2"); throw new Exception("TASK 2 EXCEPTION"); });

        Thread.Sleep(1000);

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

        Thread.Sleep(1000);

        Console.ReadKey();
    }

    private static void Unobserved(object o, UnobservedTaskExceptionEventArgs e)
    {
        e.SetObserved(); // optional
        foreach (var ex in e.Exception.InnerExceptions)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

【讨论】:

  • 您通常不必在发布模式下运行。如果您将任务开始移动到辅助方法,您也会在调试版本中看到未观察到的异常触发。
【解决方案2】:

还没有答案,但我觉得它有点有趣。我正在查看 GitHub 上的源代码。唯一调用事件处理程序的地方是 TaskScheduler 类中的 PublishUnobservedTaskException 方法。

调用PublishUnobservedTaskException 的唯一地方是来自finalizer of TaskExceptionHolder。但是,在调用 PublishUnobservedTaskException 之前必须满足一些条件,正如您在该源代码中看到的那样。

我有 enabled debugging the .NET source code,但我得到的 TaskExceptionHolder 版本与 GitHub 上的不同,它显然与我试图创建的断点不匹配。所以我不能确切地确认为什么它没有被调用,而且我今晚已经没时间了。

甚至可能值得为此 over at GitHub 创建一个问题。

【讨论】:

  • 在调试模式下,直到整个方法完成后,任务才会被垃圾收集。所以你可以在调试器中看到变量的值。在发布模式下,在方法结束之前积极收集变量。因此,接受的答案有效。
猜你喜欢
  • 2017-10-13
  • 2012-08-03
  • 1970-01-01
  • 2015-03-31
  • 1970-01-01
  • 1970-01-01
  • 2019-07-26
  • 1970-01-01
  • 2013-06-03
相关资源
最近更新 更多