Mit MessageBox zu zeigen, Ausnahme Angaben in Multithread-Anwendung
Hallo, ich arbeite mit Windows forms und versucht die MessageBox für die Ausnahmebehandlung.
Das seltsame dabei ist, dass der MessageBox erscheint nur nach der Haupt-form ("Form1" im code unten) geschlossen ist.
public class Worker {
/* edited (see below)
public void doWork() {
try {
//do something
client.Connect(serverAddress);
stream = client.GetStream();
}
catch(Exception e) {
MessageBox.Show(e.ToString(),
"This will not show up until Form1 is closed");
}
}
*/
}
public class Form1 {
/* edited (see below)
* public void threadProc() {
* Worker worker = new Worker();
* worker.doWork();
* }
*/
void button_Click(object sender, EventArgs e) {
//create a thread that will end up throwing an exception
Thread thread = new Thread(threadProc);
thread.Start();
}
}
Was könnte ein besserer Weg, um MessageBox für die Ausnahmebehandlung?
...Also ich habe einige codes für die MessageBox-ing in den UI-thread, aber das problem bleibt.
public class WorkExceptionArgs : EventArgs {
public Exception e;
public WorkExceptionArgs (Exception e) { this.e = e; }
}
public partial class Worker1 { //renamed (Worker->Worker1)
/* (edited) Now Worker1 doesn't trigger any event (see below)
public event EventHandler<WorkExceptionArgs> workException;
*/
public void doWork() {
try {
//do something
client.Connect(serverAddress);
stream = client.GetStream();
}
catch(Exception e) {
/* (edited) suppose Worker1 never throws any exception (see below)
* //trigger event that will cause MessageBox-ing by UI thread
* workException(this, new WorkExceptionArgs(e));
*/
}
}
}
public partial class Form1 {
public void threadProc() {
Worker1 worker1 = new Worker();
/* (edited) Now Worker1 never throws any exception
* worker.workException += new EventHandler<WorkException>(worker_WorkException);
*/
worker1.doWork();
//(added) After doWork() is done, Form1 creates Worker2
Worker2 w2 = new Worker2(this, this.form2);
w2.workException += new EventHandlerArgs<WorkExceptionArgs>(form2.worker2_WorkException);
w2.doSomeOtherWork();
}
/* public void worker_WorkException(object sender, WorkExceptionArgs eArg) {
* MessageBox.Show(eArg.e.ToString(), "Still not showing");
* } */
Form2 form2 = new Form2(); //(added) At first form2 is hidden (see below)
}
Eigentlich gab es eine andere form und ein anderer Arbeiter. Einmal Arbeiter(Worker1) aus Verbindung zu dem server, Form1 versteckt (.Hide()), Form2 zeigt (.Show()), und Worker2 beginnt die Arbeit mit der Verbindung Worker1 gemacht.
public class Worker2 {
Worker2(Worker1 w1, Form2 frm2) { this.w1=w1; this.frm2=frm2; }
public Worker1 w1;
public Form2 frm2;
public event EventHandler<WorkExceptionArgs> workException;
public void doSomeOtherWork() { //do some other, using data in Worker 1.
try { //This will throw an exception
BinaryFormatter formatter = new BinaryFormatter();
MyObj mo = (MyObj)formatter.Deserialize(w1.getStream());
}
catch(Exception e) {
workException(this, new WorkExceptionArgs(e));
}
}
}
public class Form2 {
public Form2(Form1 frm1) { //to switch from frm1 to frm2
InitializeComponent();
this.frm1 = frm1;
}
public Frm1 frm1 {get;set;}
public void worker2_WorkException(object sender, WorkExceptionArgs ea) {
MessageBox.Show(this, ea.e.ToString(), "SHOWS ONLY IF FORM2 IS CLOSED");
}
}
public partial class Form1 {
delegate void switchWindow_Callback();
public void switchWindow() { this.Hide(); form2.Show(); }
public void switchWindowCb(object sender, EventArgs e) {
if(this.InvokeRequired) {
SwitchWindow_Callback hcb = new SwitchWindow_Callback(switchWindow);
this.Invoke(hcb, new object[] {});
}
else { this.switchWindow(); }
}
}
- Haben Sie ging durch den code im debug-Modus?
InformationsquelleAutor Jeffrey Goines | 2012-09-10
Schreibe einen Kommentar Antworten abbrechen
Du musst angemeldet sein, um einen Kommentar abzugeben.
Eigentlich ich Wette, die MessageBox erscheint hinter die wichtigste form, und Sie einfach nicht sehen, bis Sie es schließen.
Wären Sie viel besser dran lassen der UI-thread (die, die erstellt und besitzt
Form1
) die MessageBox-ing. Sie entweder wollen, um Ereignisse oder auf sonstige Weise eine Fehler-callback-Delegaten in Ihrem Arbeiter-Klasse.Jedoch
BackgroundWorker
vielleicht lohnt sich hier eher, als zu versuchen, Rollen Sie Ihre eigenen. Vorausgesetzt, es ist eine schwerwiegende Ausnahme, die Sie speichern und abrufen von Fehler-Zustand, und ein Ereignis wird automatisch aufgerufen, wenn der thread beendet ist.Sollte man wirklich sperren die doWork-Methode, so dass mehrere threads keinen Zugriff auf Sie in der gleichen Zeit, die Sie benötigen, in die Warteschlange.
Blick in "das verbinden der Fäden". Stell dir vor, wenn Sie bekommen zwei Ausnahme bei der gleichen Zeit. Ihre app wird Sie Umfallen. Sperren Sie den Bereich ab, dass code dupliziert werden wiederholt, bildet sich eine Warteschlange für Ihre Themen, den Bereich zu betreten der code, der die Ausnahme behandelt.
Als lc angegeben ist, ist es ziemlich wahrscheinlich, dass Ihre Meldung erscheint hinter dem Hauptformular, und daher sehen Sie nur, wenn das Hauptformular geschlossen wird.
Das Modell, das ich verwenden, um befassen sich mit nicht behandelte exceptions in Windows Forms-Anwendung sieht wie folgt aus:
Den erste Zeile sagt, dass Sie möchten, zu fangen, werden alle nicht behandelten Ausnahme und beschäftigen sich mit sich selbst, anstatt sich von der WinForms-Infrastruktur umzugehen. Beachten Sie, dass aus .NET 4 und höher, diese Einstellung funktioniert nicht für eine Ausnahme, die korrumpiert Prozess-Status (zum Beispiel OutOfMemory).
Wenn Sie eine unbehandelte Ausnahme auf einem UI-thread, die zweite Zeile löst eine Prozedur, die Sie erstellen aufgerufen *App_UiThreadException*. Das ist, wo Ihr MesssageBox code sollte gehen.
Wenn Sie eine unbehandelte Ausnahme auf einem nicht-UI-thread, die Letzte Zeile löst eine Prozedur, die Sie erstellen aufgerufen *App_NonUiThreadException*. Das ist, wo Ihr MesssageBox code sollte gehen.