我正在使用Topaz块实现对Azure调用的重试处理。我已经实现了自定义指数退避重试策略。但是,我没理解这个之间的区别:
var result = await RetryPolicy.ExecuteAsync(async () => await SomeAsyncOperation());
VS
var result = await RetryPolicy.ExecuteAsync( () => SomeAsyncOperation());
根据文档,RetryPolicy.ExecuteAsync将重复执行异步任务,直到满足retrypolicy,因此第一个解决方案似乎正确,因为它等待异步操作的结果。但是,我尝试了两种方式,它们似乎工作方式相似。我还看到了第二种情况的例子like this one和this one 。哪一个是正确的?
答案 0 :(得分:3)
这是在代码中引入冗余等待的一种非常普遍的现象。
示例:简而言之,我们正在考虑这样的事情。
public Task ExecuteAsync(Func<Task> taskAction)
{
return taskAction();
}
(1) await ExecuteAsync( () => Task.Delay(5000));
vs :
(2) await ExecuteAsync( async () => await Task.Delay(5000));
在(1)中,您正在等待传递给重试策略的代理创建的任务。
在(2)中,您正在等待另一项任务,这是一个多余的任务, 你的内心等待等待你在(1)中等待的任务,在调用ExecuteAsync时会为你创建一个不同的任务。
它的工作原理是因为您的代码行为相同,它仍然等待ExecuteAsync返回的任务。 通过创建一个额外的任务(没有充分的理由),它只是做了一些更重的工作。
这里的道德是等待你想要的任务。
另外:
还有一些防御性冗余等待,但也有一些是至关重要的,似乎是多余的。
例如:
进行此读取操作 在异步(用于exmpale I / O)操作完成之前,不应该处理连接。
await DoSomeReadingAsync();
public async Task DoSomeReadingAsync()
{
using(var connection = new Connection())
{
await SomeReadOperationAsync(connection);
}
}
如果你在没有等待它的情况下返回内部任务,它将是destorus 因为连接将在内部异步操作完成之前处理。
await DoSomeReadingAsync();
public Task DoSomeReadingAsync()
{
using(var connection = new Connection())
{
return SomeReadOperationAsync(connection);
}
}