Gibt es eine elegante Lösung zum Schreiben von asynchronen Delegaten in C# (Unity)

Gibt es eine elegante Lösung zum Schreiben von asynchronen Delegaten in C# (Unity)

Lösung für Gibt es eine elegante Lösung zum Schreiben von asynchronen Delegierten in C# (Unity)
ist unten angegeben:

Ich bin damit vertraut, wie man allgemeine Delegates schreibt und sie abonniert, aber gibt es eine Möglichkeit, die Nützlichkeit von Delegates (Anmeldung und Abmeldung von anderen Klassen) mit der erwarteten Funktionalität zu nutzen?

Zum Beispiel mit einem einfachen Delegaten wie diesem:

public delegate void SimpleDelegate();
public static SimpleDelegate OnDelegateInvoke;

Ich kann es dann von einer anderen Klasse abonnieren wie:

    public void SomeFunction(){};

    OnDelegateInvoke += SomeFunction();

Das gewünschte Verhalten ist, dass der OnDelegateInvoke-Aufruf abwartbar ist, also wartet er dort, bis alle abonnierten Funktionen abgeschlossen sind:

     await OnDelegateInvoke?.Invoke();
     await DoSomethingThatNeedsAboveCompleted();

Ich habe versucht, die Delegaten mit einem Task-Rückgabetyp zu schreiben, aber meines Wissens würde das nicht funktionieren, da es mehrere Funktionen gibt, die mehrere Tasks zurückgeben, sodass das await nur auf den Abschluss der ersten Task warten würde.

Da ich darüber nachdenke, bin ich mir auch nicht sicher, ob dies das Paradigma, warum Delegierte nützlich sind, vollständig durchbricht, daher sind Antworten darauf ebenfalls willkommen.

Sie könnten dies mit Delegaten tun, die einen Task zurückgeben :

public delegate Task SimpleAsyncDelegate();
public static SimpleAsyncDelegate OnAsyncDelegateInvoke;

Um alle hinzugefügten Delegaten aufzurufen und abzuwarten, rufen wir sie einzeln auf und warten auf den erzeugten Task s:

var delegateTasks = OnAsyncDelegateInvoke.GetInvocationList()
    .Cast<SimpleAsyncDelegate>()
    .Select(del => del.Invoke());
await Task.WhenAll(delegateTasks);

Ein Beispiel mit und ohne Erwartung finden Sie in dieser Geige.

Um die Frage in den Kommentaren zu beantworten, denke ich, dass Sie einer allgemeineren Art des Wartens auf alle Delegierten am nächsten kommen, ist eine Hilfsklasse ähnlich der folgenden:

public class DelegateHelper
{
    public static async Task WhenAllDelegates(Delegate del)
    {
        var delegateTasks = del.GetInvocationList()
            .Select(del => del.DynamicInvoke())
            .Where(obj => obj is Task)
            .Cast<Task>();
        await Task.WhenAll(delegateTasks);
    }
}

Sie können es wie folgt verwenden:

await DelegateHelper.WhenAllDelegates(OnAsyncDelegateInvoke);

HINWEIS: Für den generischen Zweck müssen wir DynamicInvoke verwenden , die laut dieser Antwort deutlich schlechter abschneidet. Ob diese Leistung wirklich ein Problem darstellt, hängt vom Anwendungsfall ab, sodass Sie testen können, ob es sich lohnt.