我正在使用后台工作程序,发现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处理程序异常中会出现文本线程错误catched'test exception 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''
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处理程序
似乎只对RunWorkerCompleted事件执行GetBaseException。
答案 0 :(得分:1)
无论出于何种原因,框架都会针对您抛出的异常调用Exception.GetBaseException
并使用 异常传递到ThreadException
事件。如果您不想这样做,请不要传入基本/内部异常。