在dotnetcoreapp2.0

时间:2018-12-21 23:46:23

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

以下代码在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帖子中,我看到了在项目文件中使用以下代码段的建议,但仅适用于.net Framework 4.0+项目。如果.netcore项目文件有一个等效项,那可能就是我所需要知道的。

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

2 个答案:

答案 0 :(得分:1)

还没有答案,但是我觉得这很有趣。我正在看GitHub上的源代码。调用事件处理程序的唯一位置是来自TaskScheduler类中的PublishUnobservedTaskException方法。

调用PublishUnobservedTaskException的唯一位置是来自finalizer of TaskExceptionHolder的位置。但是,如您在该源代码中所见,在调用PublishUnobservedTaskException之前必须满足一些条件。

我有enabled debugging the .NET source code,但是我得到的TaskExceptionHolder版本与GitHub上的版本不同,并且显然与我要创建的断点不匹配。因此,我无法确切确认为什么它没有被调用,而我今晚已经没时间了。

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

答案 1 :(得分:0)

我有同样的问题。只需尝试以 RELEASE 模式运行即可。我对其进行了测试,并且可以与控制台应用程序.net core 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);
        }
    }
}