Heim >Backend-Entwicklung >C++ >Wie gehe ich mit asynchronen Ereignissen in C# um?

Wie gehe ich mit asynchronen Ereignissen in C# um?

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2025-01-08 12:37:42766Durchsuche

How to Handle Asynchronous Events in C#?

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

  • Auswirkungen auf das Design: Die Verwendung asynchroner Ereignishandler kann das Design Ihrer Anwendung ändern. Berücksichtigen Sie daher die möglichen Auswirkungen sorgfältig.
  • Komplexität: Benutzerdefinierte Delegatenmethoden erhöhen die Komplexität, stellen jedoch die Kompatibilität mit vorhandenen Ereignismustern sicher.
  • Leistung: Ein registrierungsbasierter Ansatz ist möglicherweise effizienter, da er den Reflexionsaufwand beim Aufrufen von Handlern vermeidet.

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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn