繁体   English   中英

当等待在传递给异步lambda表达的函数中时,异步方法缺少等待操作员警告

[英]Async method lacks await operators warning when the await is in a function passed to an async lambda expresion

我有以下异步方法,如果发生故障,这是一个更简单的等待和重试:

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(...)”来在后台线程上执行CPU绑定的工作。

...并将调用代码更改为此可解决问题:

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

除了使用Task.Run()之外,还有其他方法可以实现这种简单情况的并行性吗? 您看到带有Task.Run()的最新代码有什么缺点吗?

首先,我建议使用Polly 它被广泛使用,经过了广泛的测试,并且对异步和同步使用都具有本地支持。

但是,如果您想继续使用自己的,可以添加一个同步等效项:

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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM