【发布时间】:2014-09-02 08:24:51
【问题描述】:
似乎在属性的 Set 方法中发生的异常不会冒泡到应用程序的 ThreadException 事件。
我们使用该事件和 AppDomain.CurrentDomain.UnhandledException 事件来捕捉应用程序中发生的任何意外事故。异常详细信息会写入日志,以便我们的支持和开发团队可以更好地评估问题。遗憾的是,在这种特殊情况下,Catch All 似乎不够。
StackOverflow 上有几个类似的问题,但没有解决全局异常处理没有捕获异常的问题。我已经知道我们可以修复它,所以不会发生异常。我们可以为每个 setter 添加一个 TryCatch 块。我们可以将 BindingComplete 事件添加到每个数据绑定并以这种方式获取异常。但这一切都违背了在任何其他情况下都可以完美工作的全局异常处理的目的。
- How do I 'globally' catch exceptions thrown in object instances
- Data Binding and throwing exception in setter
- Neither Application.ThreadException nor AppDomain.CurrentDomain.UnhandledException are respected
要重现此问题,只需创建一个带有文本框的表单,将文本框绑定到属性并在属性的 set 方法中引发异常。将 ThreadException 和 UnhandledException 事件添加到 program.cs。运行程序并在文本框中键入以触发异常。调试器将在异常上中断,按继续 (F5) 让异常冒泡,就像在调试器之外一样。任何正常的异常都会在这些事件中结束,但这次不会。
Form1.cs
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
textBox1.DataBindings.Add("Text", this, "TestValue", true, DataSourceUpdateMode.OnPropertyChanged);
}
private string _TestValue = "";
public string TestValue
{
get{return _TestValue;}
set
{
_TestValue = value;
throw new Exception("Something bad happened in here");
}
}
Program.cs
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
Application.ThreadException += ThreadExceptionHandler;
AppDomain.CurrentDomain.UnhandledException += new System.UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
Application.Run(new Form1());
}
private static void ThreadExceptionHandler(object sender, System.Threading.ThreadExceptionEventArgs args)
{
try
{
//RR.Common.ErrorLogRt.WriteError(args.Exception.StackTrace.ToString(), args.Exception.Message.ToString(), true);
MessageBox.Show(args.Exception.Message);
}
catch
{
MessageBox.Show("Error writing to exception log. This program will now terminate abnormally.");
Application.Exit();
}
}
static void CurrentDomain_UnhandledException(object sender, System.UnhandledExceptionEventArgs e)
{
try
{
if (e != null)
{
Exception ex = e.ExceptionObject as Exception;
//RR.Common.ErrorLogRt.WriteError(ex.StackTrace.ToString(), ex.Message.ToString(), true);
MessageBox.Show(ex.Message);
}
else
{
MessageBox.Show("Unhandled Error: " + e.ToString());
}
}
catch
{
MessageBox.Show("Error writing to exception log. This program will now terminate abnormally.");
Application.Exit();
}
}
static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
try
{
if (e != null && e.Exception != null && e.Exception.InnerException != null)
{
//The unobserved exception is always the same, The actual exception that cause it will be the inner exception.
Exception ex = e.Exception.InnerException;
MessageBox.Show(e.Exception.Message);
//RR.Common.ErrorLogRt.WriteError(ex.StackTrace.ToString(), ex.Message.ToString(), true);
}
else
{
MessageBox.Show("Unhandled Error: " + e.ToString());
}
}
catch
{
MessageBox.Show("Error writing to exception log. This program will now terminate abnormally.");
Application.Exit();
}
}
}
【问题讨论】:
标签: c# .net data-binding exception-handling