Какой самый эффективный способ дождаться завершения действия?

Можно ли использовать Task или UniTask в следующем коде? 

```csharp
public event Action<int> Event;

public async void Main()
{
    await Example(Event);
}

public async Task<T> Example<T>(Action<T> action)
{
    //ожидание invoke action
}
```
  • 13 ноября 2024 г. 7:23
Ответы на вопрос 1
Да, вы можете использовать `Task` или `UniTask` для ожидания завершения действия в вашем коде. Для этого вам нужно немного изменить ваш метод `Example`, чтобы он мог ожидать вызова события.

Вот пример того, как вы можете реализовать это с помощью `Task`:

```csharp
using System;
using System.Threading.Tasks;

public class ExampleClass
{
    public event Action<int> Event;

    public async void Main()
    {
        int result = await Example();
        // Обработка результата
    }

    public Task<int> Example()
    {
        var tcs = new TaskCompletionSource<int>();

        // Подписываемся на событие
        Action<int> handler = null;
        handler = (value) => 
        {
            // Отменяем подписку
            Event -= handler;

            // Завершаем Task с результатом
            tcs.SetResult(value);
        };

        Event += handler;

        // Возвращаем Task
        return tcs.Task;
    }
}
```

### Объяснение:
1. Мы используем `TaskCompletionSource<int>` (в данном случае `tcs`), чтобы создать задачу, которую мы можем завершить позже, когда событие произойдёт.
2. Внутри метода `Example` мы добавляем обработчик события, который вызывает `SetResult` для `TaskCompletionSource`, когда событие вызывается. После этого мы также отписываемся от события, чтобы избежать утечек памяти.
3. Метод `Example` возвращает Task, который можно ожидать в методе `Main`.

Аналогично, вы можете сделать то же самое с `UniTask`, если вы используете UniRx или подобные библиотеки.

Вот как это может выглядеть с `UniTask`:

```csharp
using System;
using Cysharp.Threading.Tasks;

public class ExampleClass
{
    public event Action<int> Event;

    public async void Main()
    {
        int result = await Example();
        // Обработка результата
    }

    public UniTask<int> Example()
    {
        var tcs = new UniTaskCompletionSource<int>();

        // Подписываемся на событие
        Action<int> handler = null;
        handler = (value) => 
        {
            // Отменяем подписку
            Event -= handler;

            // Завершаем UniTask с результатом
            tcs.TrySetResult(value);
        };

        Event += handler;

        // Возвращаем UniTask
        return tcs.Task;
    }
}
```

В этом примере аналогично используем `UniTaskCompletionSource<int>`, чтобы завершить задание, когда событие произойдёт.
Похожие вопросы