似乎在属性的Set方法中发生的异常不会冒泡到应用程序的ThreadException事件。
我们将该事件与AppDomain.CurrentDomain.UnhandledException事件一起使用,以捕获应用程序中发生的任何意外情况。将异常详细信息写入日志,以便我们的支持和开发团队可以更好地评估问题。可悲的是,在这种特殊情况下,看起来“全部捕获”不足。
在StackOverflow上有几个类似的问题,但是没有答案解决全局异常处理无法捕获异常的问题。我已经知道我们可以修复它,因此不会发生任何异常。我们可以向每个设置器添加一个TryCatch块。我们可以将BindingComplete事件添加到每个数据绑定中,并以这种方式获取异常。但是,所有这些都违背了具有全局异常处理功能的目的,该功能在任何其他情况下都可以完美运行。
要重现此问题,只需创建带有文本框的表单,将文本框绑定到属性,然后在属性的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();
}
}
}
Binding.FormattingEnabled属性的备注
将此属性设置为true还可以启用错误处理行为,并引发BindingComplete事件。通过检查BindingCompleteEventArgs参数的BindingCompleteState属性,此事件的处理程序可以根据绑定过程中的成功,错误或异常采取适当的措施。
internal bool PushData(bool force)
{
Exception ex = null;
if (!force && this.ControlUpdateMode == ControlUpdateMode.Never)
{
return false;
}
if (this.inPushOrPull && this.formattingEnabled)
{
return false;
}
this.inPushOrPull = true;
try
{
if (this.IsBinding)
{
object value = this.bindToObject.GetValue();
object propValue = this.FormatObject(value);
this.SetPropValue(propValue);
this.modified = false;
}
else
{
this.SetPropValue(null);
}
}
catch (Exception ex2)
{
ex = ex2;
if (!this.FormattingEnabled)
{
throw;
}
}
finally
{
this.inPushOrPull = false;
}
if (this.FormattingEnabled)
{
BindingCompleteEventArgs bindingCompleteEventArgs = this.CreateBindingCompleteEventArgs(BindingCompleteContext.ControlUpdate, ex);
this.OnBindingComplete(bindingCompleteEventArgs);
return bindingCompleteEventArgs.Cancel;
}
return false;
}
如您所见,将第4个参数传递为true:DataBindings.Add("Text", this, "TestValue", true
负责在内部捕获异常PushData
并将其传递给BindingComplete
事件。除了启用格式设置外,没有其他方法(除外AppDomain.CurrentDomain.FirstChanceException
)在其他地方查找异常BindingComplete
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句