I've encountered a strange difference between a program running in VS2005 and running the executable directly. Essentially, when an exception is thrown in a method inside an Application.DoEvents()
call, the exception can be caught when running inside Visual Studio. When running the compiled executable, the exception is not caught and the program crashes.
Here is some simple code to demonstrate the problem. Assume standard winforms boilerplate and two buttons and a label.
To run this, click the start button to start the 10 second count. Before 10 seconds elapses, press the abort button. and an exception will be thrown inside the DoEvents()
. The exception should be caught. This only happens when running inside Visual Studio.
private void StartButton_Click(object sender, EventArgs e) {
DateTime start = DateTime.Now;
try {
while (DateTime.Now - start < new TimeSpan(0, 0, 10)) {
this.StatusLabel.Text = DateTime.Now.ToLongTimeString();
Application.DoEvents();
}
MessageBox.Show("Completed with no interuption.");
} catch (Exception) {
MessageBox.Show("User aborted.");
}
}
private void ButtonAbort_Click(object sender, EventArgs e) {
throw new Exception("aborted");
}
I want to be able to catch these exceptions. Is there any way to make it work?
Update:
I'm willing to consider approaches other than the re-entrant-headache-inducing DoEvents()
. But I haven't found one that seems to work better. My scenario is that I have a long running loop which is controlling some scientific instruments, and frequently has to wait for a temperature to stabilize or something. I want to give my users the ability to abort the process, so I have an abort button that simply throws a custom exception, that I intend to catch at the site where the process is originally kicked off. It seemed to be a perfect solution. Except for the fact that it doesn't work for some reason.
If it's not possible to get this to work, is there a better approach?
Update 2:
When I add this as the first line of Main(), that makes it work as an executable, but not in VS, so the situation is reversed. The crazy thing is that it appears to be a no-op. I can understand how this does anything.
Application.ThreadException += delegate(
object sender,
System.Threading.ThreadExceptionEventArgs e
)
{ throw e.Exception; };
This is insane.