我正在使用后台工作程序,发现 RunWorkerCompleted 事件处理程序中引发的新异常在 Application.ThreadException 处理程序中不可见。例如:Program.cs 中的某处:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.ThreadException += delegate(object o, ThreadExceptionEventArgs args)
{
if (args.Exception != null)
Console.WriteLine("thread error {0}", args.Exception.Message);
};
Application.Run(new Form1());
}
然后在按钮中单击(仅用于测试目的)
var bw = new BackgroundWorker();
bw.DoWork += delegate(object o, DoWorkEventArgs args) { /* some calculations here */ };
bw.RunWorkerCompleted += delegate(object sender1, RunWorkerCompletedEventArgs eventArgs)
{
try
{
//in run worker completed exception occurs
throw new ApplicationException("test exception 1");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine("throwing new exception");
throw new ApplicationException(string.Format("catched '{0}'", ex.Message), ex);
}
};
bw.RunWorkerAsync();
程序输出如下:
测试异常1
抛出新异常
线程错误测试异常1
我相信在 Application.ThreadException 处理程序异常中应该出现文本线程错误捕获“测试异常 1”,而不是原始异常。
你能帮我吗 - 为什么会发生以及如何解决?这只是示例代码。实际代码中的 RunWorkerCompleted 处理程序中有几个嵌套方法。其中一些方法捕获异常,并在内部异常中抛出带有附加信息和原始异常的新异常。因此,在 Application.ThreadException 处理程序中,我不仅想获得抛出的原始异常,还想获得整个链。
谢谢
我发现 GetBaseException 不会因按钮单击引起的未处理异常而被调用(例如)
让我们假设 Program.Main 方法中有 TreadException 事件处理程序,如下所示:
Application.ThreadException += (o, args) =>
{
Console.WriteLine("BEGIN ThreadException handler");
ShowException(args.Exception);
Console.WriteLine("END ThreadException handler\r\n");
};
和 Program.ShowException 方法是这样的:
static void ShowException(Exception ex)
{
var tab = "";
while (ex != null)
{
Console.WriteLine("{1}error '{0}'", ex.Message, tab);
tab += '\t';
ex = ex.InnerException;
}
}
当代码
try
{
throw new ApplicationException("button click 1");
}
catch (Exception ex)
{
throw new ApplicationException(string.Format("BC caught '{0}'", ex.Message), ex);
}
在单击按钮时执行,它会产生以下输出:
BEGIN ThreadException 处理程序
错误'BC 捕获'按钮单击 1''
- 错误'按钮单击 1'*
END ThreadException 处理程序
如您所见 - 整个异常链都可用。
但是 ThreadException 处理程序仅显示 RunWorkerCompleted 事件处理程序中非常相似的代码的原始异常(下面的代码在按钮单击事件中执行):
var bw = new BackgroundWorker();
bw.DoWork += delegate(object o, DoWorkEventArgs args)
{
/* some calculations here */
};
bw.RunWorkerCompleted += delegate(object sender1, RunWorkerCompletedEventArgs eventArgs)
{
try
{
//in run worker completed exception occurs
Console.WriteLine("RWC exception test, throwing");
throw new ApplicationException("test exception 1");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine("RWC got exception, throwing new");
throw new ApplicationException(string.Format("RWC caught '{0}'", ex.Message), ex);
}
};
bw.RunWorkerAsync();
输出如下:
RWC 异常测试,抛出
测试异常1
RWC 有异常,抛出新的
BEGIN ThreadException 处理程序
错误“测试异常 1” ——这里只有原始异常
END ThreadException 处理程序
似乎 GetBaseException 仅针对 RunWorkerCompleted 事件执行。