ThrowUnobservedTaskExceptions 不起作用

Ani*_*aul 5 c# exception .net-4.0 task

我在 Winform 中创建了一个测试应用程序来学习任务(c#)中的异常处理。目标框架是4.0。以下是我的异常处理代码

        var task = Task.Factory.StartNew<DataTable>(() => getDataTable(Convert.ToInt32  (this.textBoxOptionVal.Text)));

        task.ContinueWith(t =>
        {
            this.dataGridViewData.DataSource = t.Result as DataTable;
            this.textBoxRetVal.Text = "Success" ;
        },
        CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.FromCurrentSynchronizationContext());

        task.ContinueWith(t =>
        {
            // Update UI (and UI-related data) here: failed status.
            // t.Exception contains the occured exception.
            AggregateException aggregateException = t.Exception;
            aggregateException.Handle(exception => true);
            this.dataGridViewData.DataSource = null;
            this.textBoxRetVal.Text = "Exception Thrown";
        },
        CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.FromCurrentSynchronizationContext());
Run Code Online (Sandbox Code Playgroud)

这很好用。getDataTable如果方法抛出任何异常,则continuewith OnlyOnFaulted执行该代码块。但后来我注释掉了块中的所有语句ContinueWith OnlyOnfaulted,并添加了一个config包含以下内容的文件

<?xml version="1.0"?>
 <configuration>
  <runtime>
    <ThrowUnobservedTaskExceptions enabled="true"/>
  </runtime>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
 </configuration>
Run Code Online (Sandbox Code Playgroud)

但问题是,即使现在,当我运行代码并且方法抛出异常时getDataTable,异常是 swallon 并且进程没有终止。可能是什么原因?请帮忙。

Hag*_*t18 1

虽然我无法回答最初的问题,但我希望提供一些替代方案来解决根本问题。值得注意的是,我尝试使用 ThrowUnobservedTaskExceptions 标志,但似乎对我来说也没有什么区别。也许是因为我们是在 .net 4.0 中构建的,它无法识别该标志。我也尝试过这些替代方案。但仍然没有任何运气。如果其他人可以回答为什么它似乎不起作用,那仍然会受到赞赏。

  • 通过设置环境变量COMPlus_ThrowUnobservedTaskExceptions(set COMPlus_ThrowUnobservedTaskExceptions=1)。

  • 通过在 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework 项中设置注册表 DWORD 值 ThrowUnobservedTaskExceptions = 1。

话虽如此,这里有一些可以帮助您度过难关的替代方案。

如果您将 .NET 4.5 或 .Net 4.0 与 Microsoft.BCL.Async nuget 包一起使用,您可以在调用之前使用 wait 关键字,这会导致观察到异常

await task.ContinueWith(t =>

如果您坚持使用 .Net 4.0 并且无法安装 Microsoft.BCL.Async 包...那么您可以尝试调用 Task.Wait()

   task.ContinueWith(t =>
    {
        this.dataGridViewData.DataSource = t.Result as DataTable;
        this.textBoxRetVal.Text = "Success" ;
    },
    CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.FromCurrentSynchronizationContext());
    task.Wait();
Run Code Online (Sandbox Code Playgroud)

通过使用 Wait 或 Await,代码实际上会关心它所调用的异步函数的结果,并且会观察发生的异常。如果不这样做,它将忽略本 MSDN 文档中指出的那些异常。从那里您将能够像处理应用程序中的任何其他异常一样简单地处理意外异常

如果这不是一个选项,您还可以使用 TaskScheduler.UnobservedTaskException 事件来侦听未观察到的异常

[STAThread]
    public static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.ThreadException += ThreadExceptionHandler;
        AppDomain.CurrentDomain.UnhandledException += new System.UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
        TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;

        Application.Run(new Form1());
    }

    static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
    {
        //log or display the exception
    }

    static void CurrentDomain_UnhandledException(object sender, System.UnhandledExceptionEventArgs e)
    {
        //log or display the exception
    }

   private static void ThreadExceptionHandler(object sender, System.Threading.ThreadExceptionEventArgs args)
    {
        //log or display the exception
    }
Run Code Online (Sandbox Code Playgroud)

关于处理未观察到的异常的良好资源 http://blogs.msdn.com/b/pfxteam/archive/2011/09/28/10217876.aspx