В асинхронном методе отсутствует предупреждение операторов ожидания, когда ожидание находится в функции, переданной асинхронному лямбда-выражению - PullRequest
0 голосов
/ 10 марта 2019

У меня есть следующий асинхронный метод, который упрощает ожидание и повтор в случае сбоев:

public async Task RetryAsync(Func<Task> _action, int _ms = 1000, int _counter = 3) {
    while (true) {
        try {
            await _action();
            return; // success!
        }
        catch {
            if (--_counter == 0)
                throw;
            await Task.Delay(_ms);
        }
    }
}

К, в теории , можно назвать так:

await RetryAsync(async () => {
    _newID = myDBFunction();
}, 300);

Так как функция, переданная методу RetryAsync , не содержит await , то, очевидно, выдается предупреждение:

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

... и изменение кода вызова для решения этой проблемы:

await RetryAsync(async () => {
    await Task.Run(() => _newID = myDBFunction(););
}, 300);

Есть ли другой способ достижения параллелизма для этого простого случая, кроме использования Task.Run () ? Какой недостаток вы видите в последнем коде с Task.Run () на нем?

1 Ответ

2 голосов
/ 11 марта 2019

Во-первых, я рекомендую использовать Полли . Он широко используется, тщательно протестирован и имеет встроенную поддержку как асинхронного, так и синхронного использования.

Но если вы хотите продолжать использовать свой собственный, вы можете добавить синхронный эквивалент:

public async Task RetryAsync(Func<Task> _action, int _ms = 1000, int _counter = 3);
public void Retry(Action _action, int _ms = 1000, int _counter = 3);

, который можно назвать таковым:

Retry(() => {
  _newID = myDBFunction();
}, 300);

Если вы хотите всегда помещать синхронный код в пул потоков, вы можете добавить перегрузку для этого:

public async Task RetryAsync(Func<Task> _action, int _ms = 1000, int _counter = 3);
public async Task RetryAsync(Action _action, int _ms = 1000, int _counter = 3) =>
    await RetryAsync(() => Task.Run(_action), _ms, _counter);

, который можно назвать таковым:

await RetryAsync(() => {
    _newID = myDBFunction();
}, 300);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...