Передача ассинхронной функции в класс?

Как в своем классе можно объявить функцию в которую передать ассинхронную функцию?

public class ScrollManager
    {
        private SomeClassEvents events; // тут хранятся события
    
        public doWork()
        {
            events.call(someData); // вызываю событие
        }
    
    
        public OnSelect(Delegate onSelectFun)
        {
            events.add(onSelectFun); // добавляю слушатель событий
        }
    
    }
    

Использую этот класс вот так:

    ScrollManager scrollManager = new ScrollManager();
    
    scrollManager.OnSelect(async () =>
    {
        await someFunc();
    });

Ответы (1 шт):

Автор решения: aepot

Как я понял, вы ищете способ вызывать пачку обработчиков события асинхронно. За реализацию шаблона проектирования Publisher/Subscriber в C# отвечает ключевое слово event, а движком для этого является делегат. У делегата есть встроенный список для обработчиков, его я и предлагаю использовать. Самый простой подходящий тип делегата под вашу задачу - Func<Task>.

Например, можно реализовать метод расширения.

public static class DelegateExtensions
{
    public static Task InvokeAsync(this Func<Task> func)
    {
        return func?.GetInvocationList() is delegate[] handlers
            ? Task.WhenAll(handlers.Cast<Func<Task>>().Select(f => f()))
            : Task.CompletedTask;
    }
}

И вот так это можно использовать

class Program
{
    public static event Func<Task> MyAsyncEvent;

    static async Task SomeAsyncMethodA()
    {
        Console.WriteLine("Task A...");
        await Task.Delay(2000);
        Console.WriteLine("Task A finished");
    }

    static async Task SomeAsyncMethodB()
    {
        Console.WriteLine("Task B...");
        await Task.Delay(1000);
        Console.WriteLine("Task B finished");
    }

    static async Task Main(string[] args)
    {
        MyAsyncEvent += SomeAsyncMethodA;
        MyAsyncEvent += SomeAsyncMethodB;

        await MyAsyncEvent.InvokeAsync();

        Console.WriteLine("Invoked");
        Console.ReadKey();
    }
}

Вывод в консоль

Task A...
Task B...
Task B finished
Task A finished
Invoked

Вариант кода с аргументами как у классического события я постил ранее на Code Review.

→ Ссылка