Heim >Backend-Entwicklung >C++ >Wie gehe ich mit asynchronen Ereignissen in C# um?
Detaillierte Erläuterung der asynchronen C#-Ereignisverarbeitung
Einführung
Der C#-Ereignismechanismus ist ein leistungsstarkes Tool zur Verarbeitung asynchroner Vorgänge. Allerdings sind traditionelle Veranstaltungen ungültig, was es unmöglich macht, auf den Abschluss ihrer Durchführung zu warten. In diesem Artikel werden verschiedene alternative Möglichkeiten zur Implementierung der asynchronen Ereignisbehandlung untersucht.
Herausforderung
Betrachten Sie den folgenden Codeausschnitt, bei dem ein Shutdown-Ereignis mit einer asynchronen Aufgabe behandelt werden muss:
<code class="language-csharp">public event EventHandler<EventArgs> GameShuttingDown; public async Task ShutdownGame() { // ... await this.NotifyGameShuttingDown(); await this.SaveWorlds(); this.NotifyGameShutDown(); // ... } private async Task SaveWorlds() { // ... }</code>
Das Problem besteht darin, dass der NotifyGameShuttingDown
-Ereignishandler keinen Rückgabewert hat und ein Aufruf innerhalb der ShutdownGame
-Methode verhindert, dass die asynchrone Speicheraufgabe abgeschlossen wird, bevor das Ereignis ausgelöst wird.
Lösung 1: Benutzerdefinierte asynchrone Ereignisdelegation
Eine Möglichkeit besteht darin, einen benutzerdefinierten Ereignisdelegaten zu definieren, der eine Aufgabe zurückgibt und die Ausführung des Wartehandlers ermöglicht:
<code class="language-csharp">public event Func<object, EventArgs, Task> Shutdown;</code>
In der ShutdownGame
-Methode kann der Handler wie folgt aufgerufen werden:
<code class="language-csharp">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>
Lösung 2: Registrierungsbasierte Methode
Eine weitere Option ist die Verwendung eines registrierungsbasierten Ansatzes, bei dem Rückrufe registriert und asynchron ausgeführt werden können:
<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>
Notizen
Empfohlen
Der empfohlene Ansatz hängt von den spezifischen Anforderungen der Anwendung ab. Für vorhandene Codebasen und stark ereignisbasierte Designs werden benutzerdefinierte Delegatenmethoden bevorzugt. Für neue Anwendungen oder Anwendungen, die nicht auf Ereignissen basieren, kann ein registrierungsbasierter Ansatz eine bessere Leistung und Flexibilität bieten.
Das obige ist der detaillierte Inhalt vonWie gehe ich mit asynchronen Ereignissen in C# um?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!