Зачем использовать Async внутри Task.Run? - PullRequest
0 голосов
/ 30 октября 2019

Работая над некоторым кодом, я наткнулся на следующее:

Подход 1:

private void MyMethod()
{
    var t = Task.Run(
        async () =>
        {
            Foo.Fim();
            await Task.Delay(5000); 
        });
    t.Wait();
}

Мы намеренно вводим задержку в 5 секунд, чтобы Fim() мог завершить свою работу. ,Требуется ввести задержку - представьте, что это вызов стороннего API, который предписывает период охлаждения 5 секунд.

Я хотел бы понять, является ли это правильным подходом для ожидания завершения операции. Чем Подход 1 отличается от следующего Подхода 2? Или есть лучший способ сделать это? Все, что нам нужно, это иметь задержку периода охлаждения и избегать блокировки пользовательского интерфейса.

Подход 2:

private void MyMethod()
{
    var t = Task.Run(
        () =>         
        {
            Foo.Fim();
            Task.Delay(5000).Wait(); // some operation which takes 5  seconds.
        });
    t.Wait();
}

1 Ответ

1 голос
/ 05 ноября 2019

Вам нужен регулятор, а удобный класс для его реализации - SemaphoreSlim:

Ограничивает количество потоков, которые могут получить доступ к ресурсу или пулуресурсов одновременно.

private SemaphoreSlim _myMethodSemaphore = new SemaphoreSlim(1);

private void MyMethod()
{
    _ = Task.Run(async () =>
    {
        await _myMethodSemaphore.WaitAsync();
        try
        {
            Foo.Fim();
        }
        finally
        {
            await Task.Delay(5000); // Impose the delay even in case of an exception
            _myMethodSemaphore.Release();
        }
    });
}

Обратите внимание, что в этом примере Wait() отсутствует. Единственный блокирующий вызов - это вызов метода Foo.Fim(). Сделав этот метод асинхронным, вы получите идеальное решение в отношении масштабируемости: await Foo.FimAsync()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...