Manchmal möchte es meinen Thread blockieren, während auf ein Ereignis gewartet wird.Blockieren und Warten auf ein Ereignis
Ich mache es in der Regel etwas wie folgt aus:
private AutoResetEvent _autoResetEvent = new AutoResetEvent(false);
private void OnEvent(object sender, EventArgs e){
_autoResetEvent.Set();
}
// ...
button.Click += OnEvent;
try{
_autoResetEvent.WaitOne();
}
finally{
button.Click -= OnEvent;
}
Es scheint jedoch, dass dies etwas sein sollte, dass ich zu einer gemeinsamen Klasse extrahieren könnte (oder vielleicht sogar etwas, das bereits im Rahmen vorhanden ist).
Ich möchte in der Lage sein, so etwas zu tun:
EventWaiter ew = new EventWaiter(button.Click);
ew.WaitOne();
EventWaiter ew2 = new EventWaiter(form.Closing);
ew2.WaitOne();
Aber ich kann nicht wirklich einen Weg finden, eine solche Klasse zu konstruieren (Ich kann nicht eine gute gültige Weg finden, das passieren Ereignis als Argument). Kann jemand helfen?
ein Beispiel geben, warum dies nützlich sein kann, sollten Sie etwas wie folgt aus:
var status = ShowStatusForm();
status.ShowInsertUsbStick();
bool cancelled = WaitForUsbStickOrCancel();
if(!cancelled){
status.ShowWritingOnUsbStick();
WriteOnUsbStick();
status.AskUserToRemoveUsbStick();
WaitForUsbStickToBeRemoved();
status.ShowFinished();
}else{
status.ShowCancelled();
}
status.WaitUntilUserPressesDone();
Das ist viel kürzer und lesbarer als der entsprechende Code mit dem zwischen vielen Methoden verteilt Logik geschrieben. Aber um WaitForUsbStickOrCancel(), WaitForUsbStickToBeRemoved und WaitUntilUserPressesDone() zu implementieren (angenommen, dass wir ein Ereignis bekommen, wenn USB-Sticks eingefügt oder entfernt werden), muss ich jedes Mal "EventWaiter" neu implementieren. Natürlich müssen Sie darauf achten, dass Sie das nie auf dem GUI-Thread ausführen, aber manchmal ist das ein lohnender Kompromiss für den einfacheren Code.
Die Alternative wäre in etwa so aussehen:
var status = ShowStatusForm();
status.ShowInsertUsbStick();
usbHandler.Inserted += OnInserted;
status.Cancel += OnCancel;
//...
void OnInserted(/*..*/){
usbHandler.Inserted -= OnInserted;
status.ShowWritingOnUsbStick();
MethodInvoker mi =() => WriteOnUsbStick();
mi.BeginInvoke(WritingDone, null);
}
void WritingDone(/*..*/){
/* EndInvoke */
status.AskUserToRemoveUsbStick();
usbHandler.Removed += OnRemoved;
}
void OnRemoved(/*..*/){
usbHandler.Removed -= OnRemoved;
status.ShowFinished();
status.Done += OnDone;
}
/* etc */
ich, dass es sehr viel schwieriger finden zu lesen. Zugegeben, es ist bei weitem nicht immer so, dass der Fluss so linear sein wird, aber wenn es so ist, mag ich den ersten Stil.
Es ist vergleichbar mit der Verwendung von ShowMessage() und Form.ShowDialog() - sie auch blockieren, bis einige "Ereignis" auftritt (obwohl sie eine Nachrichtenschleife ausführen, wenn sie auf dem GUI-Thread aufgerufen werden).
Ich bin neugierig, warum genau würden Sie dies tun wollen ... können Sie das näher erläutern? –
Ich verstehe immer noch nicht, warum du den Thread blockieren willst, anstatt nur auf das Event zu warten - was bewirkt das? –
Hast du das jemals behoben? Ich habe das gleiche Problem. – Carlo