簡體   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