Heim >Backend-Entwicklung >C++ >Wie kann man in C# sicher auf asynchrone Ereignisse warten?
Asynchrone Ereignisse in C# behandeln: Asynchrone Vorgänge sicher abwarten
Problemübersicht:
In C# sind Ereignisse normalerweise Delegaten ohne Rückgabewerte, die verwendet werden, um Abonnenten über bestimmte Ereignisse in der Anwendung zu benachrichtigen. Beim Versuch, einen asynchronen Event-Handler zu verwenden, kann jedoch ein Problem auftreten: Das Ereignis wird ausgelöst, aber die Anwendung wird geschlossen, bevor der asynchrone Handler die Ausführung abschließt.
Ereignisse mit einem asynchronen Handler abonnieren:
Um Ereignisse asynchron zu verarbeiten, wird nicht empfohlen, die Ereignissignatur selbst zu ändern, um eine Aufgabe zurückzugeben. Stattdessen können Sie eine Registrierungsmethode verwenden, die eine erwartbare Rückruffunktion akzeptiert. Dies sorgt für mehr Flexibilität und eine einfachere Integration mit Komponenten von Drittanbietern.
Umsetzung mittels Registrierungsmethode:
<code class="language-csharp">private List<Func<Task>> ShutdownCallbacks = new List<Func<Task>>(); public void RegisterShutdownCallback(Func<Task> callback) { this.ShutdownCallbacks.Add(callback); } public async Task Shutdown() { var callbackTasks = new List<Task>(); foreach (var callback in this.ShutdownCallbacks) { callbackTasks.Add(callback()); } await Task.WhenAll(callbackTasks); }</code>
In diesem Beispiel speichert die ShutdownCallbacks
-Liste Rückruffunktionen, auf die gewartet werden kann. Die Shutdown()
-Methode durchläuft diese Rückruffunktionen und wartet gleichzeitig auf sie. Dadurch wird sichergestellt, dass alle asynchronen Handler abgeschlossen sind, bevor der Herunterfahrvorgang fortgesetzt wird.
Veranstaltung über eine Anrufliste aufrufen:
Alternativ können Sie, wenn Sie das bestehende Ereignisparadigma beibehalten möchten, die GetInvocationList()
-Methode verwenden, um Handler nacheinander aufzurufen und auf die zurückgegebenen Aufgaben zu warten.
<code class="language-csharp">class A { public event Func<object, EventArgs, Task> Shutdown; public async Task OnShutdown() { Func<object, EventArgs, Task> handler = Shutdown; if (handler == null) { return; } Delegate[] invocationList = handler.GetInvocationList(); Task[] handlerTasks = new Task[invocationList.Length]; for (int i = 0; i < invocationList.Length; i++) { handlerTasks[i] = ((Func<object, EventArgs, Task>)invocationList[i])(this, EventArgs.Empty); } await Task.WhenAll(handlerTasks); } }</code>
Hier ruft OnShutdown()
den Ereignisdelegierten ab, ruft Handler auf und wartet auf deren Abschluss.
Fazit:
Asynchrone Event-Handler mögen zwar verlockend erscheinen, dieser Ansatz wird jedoch im Allgemeinen nicht empfohlen, da es zu Deadlocks und anderen Problemen kommen kann. Wie oben erwähnt, bietet die Verwendung registrierter Methoden oder Aufruflisten eine robustere und einfacher zu verwaltende Lösung für das asynchrone Warten auf Ereignisse in C#.
Das obige ist der detaillierte Inhalt vonWie kann man in C# sicher auf asynchrone Ereignisse warten?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!