是否可以在 C# class 中为多个计时器设置一个异常处理程序?
Is it possible to have one Exception handler for multiple timers in a C# class?
我有一个运行系统托盘应用程序的 C# 程序 - 在后台传输/移动/创建/编辑文件。
如果用户手册删除程序正在使用的文件,有很多异常处理和循环处理可以防止程序崩溃/卡住。
不幸的是,运行 所在的其中一台计算机出现程序崩溃。电脑太难搞了,而且不能装调试软件(就是外面的嵌入式PC,没有网络)。
我已尝试找出崩溃的原因(例如未处理的异常),但没有找到任何原因,也无法访问 PC,因为它位于远程位置。
我希望找到一种方法来使用 AppDomain / UnhandledExceptionEventHandler 来捕获所有未处理的异常并将它们记录下来以供诊断。
但是,我在 class "DoSomething.class" 的办公室中(故意)创建的异常正在使 WinForm 应用程序崩溃,而不是记录异常错误。
我的代码是:
//Current domain for the unhandled exception handling
AppDomain currentDomain;
[SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlAppDomain)]
public MainForm()
{
InitializeComponent();
currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledExceptionHandler);
CreateTimer.Interval = Settings.Default.CreateTimer;
CreateTimer.Start();
RunCopyProtocol();
ChangeFilesTimer.Interval = 10000;
ChangeFilesTimer.Start();
RunChangeFiles();
throw new Exception("ABC");
}
public void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args)
{
try
{
Exception ex = (Exception)args.ExceptionObject;
SetLabel(ex);
}
finally { }
}
private string SetLabel(Exception ex)
{
String str;
str = ex.Message;
Label1.Text = str;
return str;
}
private void ChangeFilesTimer_Tick(object sender, EventArgs e)
{
RunChangeFiles();
throw new Exception("2");
}
为什么throw new异常不调用unhandled exception错误?
我将如何使用 AppDomain 获取未处理的异常处理程序来处理 RunChangeFiles 中的此异常/异常?
AppDomain 上的代码基于 MSDN examples
如果您的计时器是 System.Timers.Timer
MSDN here:
记录了原因
The Timer component catches and suppresses all exceptions thrown by event handlers for the Elapsed event.
看看这个类似的问题:
How do I get the Exception that happens in Timer Elapsed event?
您必须捕获在 elapsed 处理程序中抛出的异常,并在 ThreadPool 线程上重新抛出它们。
使用上面的代码并扩展引用问题的答案:
private void ChangeFilesTimer_Tick(object sender, EventArgs e)
{
try
{
RunChangeFiles();
}
catch (Exception ex)
{
ThreadPool.QueueUserWorkItem(
_ => { throw new Exception("Exception on timer thread.", ex); });
}
}
如果您的计时器是 System.Windows.Forms.Timer
,那么您将需要挂接到 Application.ThreadException 事件以处理未处理的异常。
在调用 Application.Run()
之前订阅此事件。
您还可以在重新抛出异常之前在本地异常处理块中处理 Exception
的日志记录。
try
{
/// ...
}
catch (Exception ex)
{
if (ex is ArgumentException)
{
/// handle known or specific exceptions here
}
else
{
/// log then rethrow unhandled exceptions here
logExceptions(ex);
throw;
}
}
我有一个运行系统托盘应用程序的 C# 程序 - 在后台传输/移动/创建/编辑文件。
如果用户手册删除程序正在使用的文件,有很多异常处理和循环处理可以防止程序崩溃/卡住。
不幸的是,运行 所在的其中一台计算机出现程序崩溃。电脑太难搞了,而且不能装调试软件(就是外面的嵌入式PC,没有网络)。
我已尝试找出崩溃的原因(例如未处理的异常),但没有找到任何原因,也无法访问 PC,因为它位于远程位置。
我希望找到一种方法来使用 AppDomain / UnhandledExceptionEventHandler 来捕获所有未处理的异常并将它们记录下来以供诊断。 但是,我在 class "DoSomething.class" 的办公室中(故意)创建的异常正在使 WinForm 应用程序崩溃,而不是记录异常错误。
我的代码是:
//Current domain for the unhandled exception handling
AppDomain currentDomain;
[SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlAppDomain)]
public MainForm()
{
InitializeComponent();
currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledExceptionHandler);
CreateTimer.Interval = Settings.Default.CreateTimer;
CreateTimer.Start();
RunCopyProtocol();
ChangeFilesTimer.Interval = 10000;
ChangeFilesTimer.Start();
RunChangeFiles();
throw new Exception("ABC");
}
public void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args)
{
try
{
Exception ex = (Exception)args.ExceptionObject;
SetLabel(ex);
}
finally { }
}
private string SetLabel(Exception ex)
{
String str;
str = ex.Message;
Label1.Text = str;
return str;
}
private void ChangeFilesTimer_Tick(object sender, EventArgs e)
{
RunChangeFiles();
throw new Exception("2");
}
为什么throw new异常不调用unhandled exception错误? 我将如何使用 AppDomain 获取未处理的异常处理程序来处理 RunChangeFiles 中的此异常/异常?
AppDomain 上的代码基于 MSDN examples
如果您的计时器是 System.Timers.Timer
MSDN here:
The Timer component catches and suppresses all exceptions thrown by event handlers for the Elapsed event.
看看这个类似的问题: How do I get the Exception that happens in Timer Elapsed event?
您必须捕获在 elapsed 处理程序中抛出的异常,并在 ThreadPool 线程上重新抛出它们。
使用上面的代码并扩展引用问题的答案:
private void ChangeFilesTimer_Tick(object sender, EventArgs e)
{
try
{
RunChangeFiles();
}
catch (Exception ex)
{
ThreadPool.QueueUserWorkItem(
_ => { throw new Exception("Exception on timer thread.", ex); });
}
}
如果您的计时器是 System.Windows.Forms.Timer
,那么您将需要挂接到 Application.ThreadException 事件以处理未处理的异常。
在调用 Application.Run()
之前订阅此事件。
您还可以在重新抛出异常之前在本地异常处理块中处理 Exception
的日志记录。
try
{
/// ...
}
catch (Exception ex)
{
if (ex is ArgumentException)
{
/// handle known or specific exceptions here
}
else
{
/// log then rethrow unhandled exceptions here
logExceptions(ex);
throw;
}
}