Подтвердить что ты не робот

Вызов метода асинхронного использования с помощью Task.Run кажется неправильным?

Недавно я купил этот код, написанный подрядчиком, с которым мы работали для нас. Это либо дьявольски умный, либо глупый (я думаю, последнее, но я хотел второго мнения). Я не увеличиваю скорость до async await.

В основном он работал следующим образом:

public bool Send(TemplatedMessageDto message)
{
    return Task.Run(() => SendAsync(message))
        .GetAwaiter()
        .GetResult();
}

public async Task<bool> SendAsync(TemplatedMessageDto message)
{
    //code doing stuff
    var results = await _externalresource.DothingsExternally();
    //code doing stuff
}

Теперь, насколько я понимаю, первый Task.Run() бессмыслен и неэффективен? и должно быть действительно:

public bool Send(TemplatedMessageDto message)
{
    return SendAsync(message))
    .GetAwaiter()
    .GetResult();
}

public async Task<bool> SendAsync(TemplatedMessageDto message)
{
    //code doing stuff
    var results = await _externalresource.DothingsExternally();
    //code doing stuff
}

Я также не уверен, что это действительно асинхронный метод, потому что он все равно будет ждать, правильно? Я думаю, что только преимущество (даже переписанное) - освободить основной рабочий поток.

Может кто-нибудь подтвердить, что эта первая задача не должна быть там?

4b9b3361

Ответ 1

Я также не уверен, что это действительно метод async, потому что он все равно будет ждать, правильно?

Это не так, как объяснил Юваль. Вы не должны использовать синхронизацию через async.

Теперь, насколько я понимаю, первый Task.Run() бессмыслен и неэффективен?

На самом деле нет смысла использовать Task.Run таким образом.

Поскольку вы блокируете метод async (который вам не нужно делать), есть вероятность, что вы зашли в тупик. Это происходит в приложениях пользовательского интерфейса и asp.net, где у вас есть SynchronizationContext.

Использование Task.Run очищает, что SynchronizationContext, поскольку оно разгружает работу до потока ThreadPool и устраняет риск возникновения взаимоблокировки.

Таким образом, блокировка - это плохо, но если вы в конечном итоге сделаете это с помощью Task.Run, это будет безопаснее.

Ответ 2

Я также не уверен, что это действительно метод async, потому что он все равно будет ждать, правильно?

Что сделал ваш подрядчик, используйте синхронизацию по асинхронному анти-шаблону. Вероятно, он сделал это, чтобы спасти себя от создания дополнительного метода, который выполняет свою работу синхронно. Он необязательно вызывает Task.Run и немедленно блокирует его с помощью GetResult.

Использование GetAwaiter().GetResult() будет распространять внутреннее исключение, если это произойдет, вместо обернутого AggregateException.

Я думаю, что только преимуществом (даже переписанным) является освобождение основного рабочего потока.

Как ваша версия, так и его будут блокировать основной поток во время выполнения, в то время как он также сделает это, используя threadpool thread. Как упоминалось в Bar, это может помочь избежать взаимоблокировок с проблемами, связанными с маршалингом контекста синхронизации. Я бы рекомендовал создать синхронный эквивалент при необходимости.