栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

TAP全局异常处理程序

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

TAP全局异常处理程序

如果我理解正确,这实际上是一个 问题。我最初投票决定将其关闭,但现在撤回了我的投票。

重要的是要了解如何将

async Task
方法内引发的异常传播到方法外。最重要的是,处理任务完成的代码需要 遵守 此类异常。

例如,这是一个简单的WPF应用程序,我在NET 4.5.1上:

using System;using System.Threading.Tasks;using System.Windows;namespace WpfApplication_22369179{    public partial class MainWindow : Window    {        Task _task;        public MainWindow()        { InitializeComponent(); AppDomain.CurrentDomain.UnhandledException +=     CurrentDomain_UnhandledException; TaskScheduler.UnobservedTaskException +=     TaskScheduler_UnobservedTaskException; _task = DoAsync();        }        async Task DoAsync()        { await Task.Delay(1000); MessageBox.Show("Before throwing..."); GCAsync(); // fire-and-forget the GC throw new ApplicationException("Surprise");        }        async void GCAsync()        { await Task.Delay(1000); MessageBox.Show("Before GC..."); // garbage-collect the task without observing its exception  _task = null; GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);        }        void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)        { MessageBox.Show("TaskScheduler_UnobservedTaskException:" +     e.Exception.Message);        }        void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)        { MessageBox.Show("CurrentDomain_UnhandledException:" +     ((Exception)e.ExceptionObject).Message);        }    }}

一旦

ApplicationException
被抛出,它就不会被观察到。无论是
TaskScheduler_UnobservedTaskException
CurrentDomain_UnhandledException
被调用。异常保持hibernate状态,直到
_task
对象被等待或等待。在上面的示例中,它从未被观察到,
因此
TaskScheduler_UnobservedTaskException
仅当任务被垃圾收集时才会被调用
。然后,将 吞噬 此异常。

AppDomain.CurrentDomain.UnhandledException
可以通过
ThrowUnobservedTaskExceptions
app.config
以下位置进行配置来启用旧的.NET
4.0行为:在该行为中会触发事件并导致应用崩溃。

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

以这种方式启用
,在异常被垃圾收集之后,而不是在引发异常的地方,

AppDomain.CurrentDomain.UnhandledException
仍将被触发。
__
TaskScheduler.UnobservedTaskException

Stephen Toub在他的“ .NET
4.5中的任务异常处理”博客文章中对此行为进行了描述。有关任务垃圾收集的部分在帖子评论中进行了描述。

方法就是这种情况

async Task
。对于
async void

方法(通常用于事件处理程序)而言,情况大不相同。让我们以这种方式更改代码:

public MainWindow(){    InitializeComponent();    AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;    TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;    this.Loaded += MainWindow_Loaded;}async void MainWindow_Loaded(object sender, RoutedEventArgs e){    await Task.Delay(1000);    MessageBox.Show("Before throwing...");    throw new ApplicationException("Surprise");}

因为

asyncvoid
没有
Task
可保留的引用(因此以后可能没有观察到或垃圾回收的内容)。在这种情况下,立即在当前同步上下文上引发异常。对于一个WPF应用程序,
Dispatcher.UnhandledException
会先启用,然后
Application.Current.DispatcherUnhandledException
,然后
AppDomain.CurrentDomain.UnhandledException
。最后,如果没有处理这些事件(
EventArgs.Handled
未设置为
true
),则无论
ThrowUnobservedTaskExceptions
设置如何,应用都会崩溃。
TaskScheduler.UnobservedTaskException

不是 在这种情况下被解雇,出于同样的原因:没有
Task



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/385846.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号