Il est parfois à bloquer mon fils en attendant qu'un événement se produise.
J'ai l'habitude de faire quelque chose comme ceci:
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;
}
Cependant, il semble que ce devrait être quelque chose que j'ai pu extraire d'une classe commune (ou peut-être même quelque chose qui existe déjà dans le cadre).
Je voudrais être capable de faire quelque chose comme ceci:
EventWaiter ew = new EventWaiter(button.Click);
ew.WaitOne();
EventWaiter ew2 = new EventWaiter(form.Closing);
ew2.WaitOne();
Mais je ne peux pas vraiment trouver un moyen de construire une telle classe (je ne peux pas trouver un bon moyen valable pour transmettre l'événement comme un argument). Quelqu'un peut-il aider?
Pour donner un exemple de pourquoi cela peut être utile, pensez à quelque chose comme ceci:
var status = ShowStatusForm();
status.ShowInsertUsbStick();
bool cancelled = WaitForUsbStickOrCancel();
if(!cancelled){
status.ShowWritingOnUsbStick();
WriteOnUsbStick();
status.AskUserToRemoveUsbStick();
WaitForUsbStickToBeRemoved();
status.ShowFinished();
}else{
status.ShowCancelled();
}
status.WaitUntilUserPressesDone();
C'est beaucoup plus concis et lisible que l'équivalent du code écrit avec la logique réparties entre plusieurs méthodes. Mais pour mettre en œuvre WaitForUsbStickOrCancel(), WaitForUsbStickToBeRemoved et WaitUntilUserPressesDone() (à supposer que nous obtenons un événement lorsque les clés usb sont insérés ou retirés) j'ai besoin de ré-écrire "EventWaiter" à chaque fois. Bien sûr, vous devez être prudent de ne jamais exécuter sur le GUI-thread, mais parfois, c'est un bon compromis pour la simple code.
L'alternative serait ressembler à ceci:
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 */
Je trouve que beaucoup plus difficile à lire. Certes, il est loin d'être toujours que le flux sera donc linéaire, mais quand il l'est, j'aime le premier style.
Il est comparable à l'utilisation ShowMessage() et de la Forme.ShowDialog() - ils également bloquer jusqu'à ce que certains "cas" se produit (bien qu'elles fonctionnent un message en boucle si elles sont appelées sur le gui-thread).