Ich habe einen merkwürdigen Unterschied zwischen einem Programm, das in VS2005 ausgeführt wird, und dem Ausführen der ausführbaren Datei direkt festgestellt. Wenn eine Ausnahme in einer Methode innerhalb eines Aufrufs Application.DoEvents()
ausgelöst wird, kann die Ausnahme bei dem Ausführen in Visual Studio gefangen werden. Wenn die kompilierte ausführbare Datei ausgeführt wird, wird die Ausnahme nicht abgefangen und das Programm stürzt ab.Können Sie Ausnahme innerhalb von Application.DoEvents() abfangen?
Hier ist ein einfacher Code, um das Problem zu demonstrieren. Angenommen, Standard Winforms Boilerplate und zwei Tasten und ein Label.
Um dies auszuführen, klicken Sie auf die Schaltfläche Start, um die Zählung von 10 Sekunden zu starten. Bevor 10 Sekunden verstreichen, drücken Sie die Abbruch-Taste. und eine Ausnahme wird innerhalb der DoEvents()
geworfen werden. Die Ausnahme sollte abgefangen werden. Dies geschieht nur, wenn Sie in Visual Studio ausgeführt werden.
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");
}
Ich möchte in der Lage sein, diese Ausnahmen zu fangen. Gibt es eine Möglichkeit, es zum Laufen zu bringen?
Update:
Ich bin bereit, Ansätze zu betrachten andere als die einspringenden-Kopfschmerzen auslösende DoEvents()
. Aber ich habe keinen gefunden, der besser zu funktionieren scheint. Mein Szenario ist, dass ich eine lange laufende Schleife habe, die einige wissenschaftliche Instrumente steuert, und häufig auf eine Temperatur warten muss, um sich zu stabilisieren oder so etwas. Ich möchte meinen Benutzern die Möglichkeit geben, den Prozess abzubrechen. Daher habe ich eine Schaltfläche zum Abbrechen, die einfach eine benutzerdefinierte Ausnahme auslöst, die ich an der Stelle abfangen möchte, an der der Prozess ursprünglich gestartet wurde. Es schien eine perfekte Lösung zu sein. Bis auf die Tatsache, dass es aus irgendeinem Grund nicht funktioniert.
Wenn es nicht möglich ist, dies zur Arbeit zu bringen, gibt es einen besseren Ansatz?
Update 2:
Als ich dies als die erste Zeile der Main() hinzufügen, dass es funktionieren als eine ausführbare, aber nicht in VS, so ist die Situation umgekehrt ist, macht. Das Verrückte ist, dass es ein No-Op zu sein scheint. Ich kann verstehen, wie das alles macht.
Application.ThreadException += delegate(
object sender,
System.Threading.ThreadExceptionEventArgs e
)
{ throw e.Exception; };
Das ist verrückt.
Ich tat es absichtlich auf diese Weise, in der Hoffnung, meinen Benutzern einen Abbruchknopf zur Verfügung zu stellen, der einen lang andauernden Prozess tötet, der die meiste Zeit damit verbringt, auf externe Instrumente zu warten. Was ist der beste Weg, dies ohne DoEvents zu tun? (siehe auch, neues Update in OP) – recursive
Verdammt, Skeet. Ich habe sorgfältig meine winzige Antwort bearbeitet, während du das redest. –
Ich habe immer gehört, dass Sie immer Threads vermeiden sollten, wenn Sie können, weil das Debuggen so schwierig ist. Der Wortlaut Ihrer Änderung deutet darauf hin, dass alle Apps, die nicht über die Benutzeroberfläche verfügen (alle Apps), Multi-Threading sein sollten. Ich bin verwirrt. – recursive