使用瞬态故障处理重试异步操作

时间:2016-12-15 22:29:59

标签: c# async-await task-parallel-library

我正在使用Topaz块实现对Azure调用的重试处理。我已经实现了自定义指数退避重试策略。但是,我没理解这个之间的区别:

  var result = await RetryPolicy.ExecuteAsync(async () => await SomeAsyncOperation());

VS

var result = await RetryPolicy.ExecuteAsync( () => SomeAsyncOperation());
根据文档,

RetryPolicy.ExecuteAsync将重复执行异步任务,直到满足retrypolicy,因此第一个解决方案似乎正确,因为它等待异步操作的结果。但是,我尝试了两种方式,它们似乎工作方式相似。我还看到了第二种情况的例子like this onethis one 。哪一个是正确的?

1 个答案:

答案 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返回的任务。 通过创建一个额外的任务(没有充分的理由),它只是做了一些更重的工作。

RetryPolicy.cs

ExecuteAsync.cs

这里的道德是等待你想要的任务。

另外:

还有一些防御性冗余等待,但也有一些是至关重要的,似乎是多余的。

例如:

进行此读取操作 在异步(用于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);
      }
  }