Async, await и что я делаю не так?

546
07 июля 2017, 03:27

Не очень силён в async/await, не могу понять, что мне студия советует сделать.

public class ManagerService
{
    public ManagerService()
    {
        Task.Run(Observe);
    }
    private async Task Observe()
    {
        while (true)
        {
            Thread.Sleep(5000);
            Debug.WriteLine("Observe");
        } 
    }
}

"В данном асинхронном методе отсутствуют операторы await, поэтому метод будет выполняться синхронно. Воспользуйтесь оператором await для ожидания неблокирующих вызовов API или оператором await Task.Run(...) для выполнения связанных с ЦП заданий в фоновом потоке."

await в моём понимание мне не нужен, так как я ждать чего либо не собираюсь, просто запускаю процесс в фоновом потоке. Использовать "await Task.Run(...)" не получается (возможно не правильно это пытаюсь сделать), и не понимаю, что это мне даст.

Вообщем вопрос в том, что я теряю, если оставляю как есть?

Answer 1

async/await в методе Observe вам вроде бы действительно не нужен. Поскольку в нем не используется ключевое слово await, то Студия говорит вам о том, что и async Task не нужен. Должно получиться так:

private void Observe()
{
    while (true)
    {
        Thread.Sleep(5000);
        Debug.WriteLine("Observe");
    } 
}

Если вы решите оставить ключевое слово async, то теряете маленькие крохи на производительности, поскольку для таких методов компилятор генерирует специальный код, вызов которого стоит дороже, чем вызов обычного метода.

Однако в методе есть один недостаток: при вызове Thread.Sleep() поток будет блокироваться и простаивать без работы. Это не очень хорошо (а иногда и вообще критично). Здесь нам как раз может помочь асинхронный вариант ожидания: Task.Delay. И теперь async/await снова имеет смысл:

private async Task ObserveAsync()
{
    while (true)
    {
        await Task.Delay(5000).ConfigureAwait(false);
        Debug.WriteLine("Observe");
    } 
}

Подробнее о том, как работает async/await и почему блокировать потоки плохо, можно почитать в другом ответе или посмотреть доклад.

Другой момент: завершение метода. Если у вас есть бесконечный цикл, то нужно предусмотреть выход из него. И если логика метода такого не предполагает, то нужно использовать некую команду извне. Для этого рекомендуется использовать CancellationToken (при этом его можно использовать как в синхронном, так и в асинхронном варианте):

// не забудьте по окончании работы вызвать Dispose()
CancellationTokenSource tokenSource = new CancellationTokenSource();
public ManagerService()
{
    Task.Run(Observe);
}
private void Observe()
{
    while (!tokenSource.Token.IsCancellationRequested)
    {
        Thread.Sleep(5000);
        Debug.WriteLine("Observe");
    } 
}
READ ALSO
Перенос строки после N символа в c#

Перенос строки после N символа в c#

Видел примеры на различных языках, но для c# не понял как это реализовать, прошу помощиЕсть текст, к примеру 20 символов

597
Как сделать приватную WebApi

Как сделать приватную WebApi

У меня есть простой апи контроллер, который я показал вышеНо каждый сможет прописать (пример - не тыкайте)"https://www

253
Конвертирование Color в ConsoleColor

Конвертирование Color в ConsoleColor

Здравствуйте, пишу программу которая получает фотографию, и рисует ее на консоли, но поскольку приложение консольное, а как вы знаете что...

227