Polly and async method: cannot convert async lambda expression to delegate Task<HttpResponseMessage>

huangapple go评论71阅读模式
英文:

Polly and async method: cannot convert async lambda expression to delegate Task<HttpResponseMessage>

问题

I am trying to use Polly to wrap an async method. How I get an error with my method, I try this:

我尝试使用Polly来包装一个异步方法。当我使用这个方法时出现错误:

var myResult = await _politicaReintentar.ExecuteAsync(async () => await Task.Delay(1000));

But I get an error that tells it cannot convert async lambda expression to delegate Task<HttpResponseMessage>, and the error is marked in await Task.Delay(1000).

但是我遇到一个错误,错误信息说它无法将异步 lambda 表达式转换为 Task<HttpResponseMessage> 委托,错误出现在 await Task.Delay(1000)

In the documentation the way to use is this:

在文档中的正确用法是这样的:

var response = await timeoutPolicy
    .ExecuteAsync(
      async () => await FooNotHonoringCancellationAsync(), // Execute a delegate which takes no CancellationToken and does not respond to cancellation.
      );

I don't see the problem, I use async and await as parameters of ExecuteAsync.

我看不出问题在哪里,我在 ExecuteAsync 的参数中使用了 asyncawait

How should I call my async method?

我该如何调用我的异步方法?

Thanks.

谢谢。

EDIT: this is the policy:

编辑:这是策略:

_politicaReintentar = HttpPolicyExtensions
    .HandleTransientHttpError() // HttpRequestException, 5XX and 408
    .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(retryAttempt));
英文:

I am trying to use Polly to wrap an async method. How I get an error with my method, I try this:

var myResult = await _politicaReintentar.ExecuteAsync(async () =&gt; await Task.Delay(1000));

But I get an error that tells it cannot convert async lambda expression to delegate Task&lt;HttpResponseMessage&gt;, and the error is marked in await Task.Delay(1000).

In the documentation the way to use is this:

var response = await timeoutPolicy
    .ExecuteAsync(
      async () =&gt; await FooNotHonoringCancellationAsync(), // Execute a delegate which takes no CancellationToken and does not respond to cancellation.
      );

I don't see the problem, I use async and await as parameters of ExecuteAsync.

How should I call my async method?

Thanks.

EDIT: this is the policy:

_politicaReintentar = HttpPolicyExtensions
    .HandleTransientHttpError() // HttpRequestException, 5XX and 408
    .WaitAndRetryAsync(3, retryAttempt =&gt; TimeSpan.FromSeconds(retryAttempt));

答案1

得分: 3

根据提供的信息,我假设您已经定义了一个策略,其中要被装饰的异步方法应返回一个HttpResponseMessage

Task.Delay并不返回HttpResponseMessage。您的策略定义必须与要被装饰的方法返回类型兼容。

英文:

Based on the so far provided information, I assume you have defined a policy where the to-be-decorated async method should return an HttpReponseMessage.

Task.Delay does not return with a HttpResponseMessage. Your policy definition must be compatible with the to-be-decorated method return type.


UPDATE #1
> I really would like to learn how to execute an async method with Polly and retry 3 times, for example. In this case, a basic case is to execute a Task.Delay()

I don't want to repeat here the documentation of Polly so, let me give you some really short summary.

In case of Polly the policy definition and its execution are separated.

Definition

The definition is done via several builder functions. In all cases you have to define the following three:

  • The to-be-decorated action is sync/async and method/function
  • The trigger(s) for which the policy should be fire
  • The chosen resilience action and its configuration

In case of your _politicaReintentar these are the following:

HttpPolicyExtensions.HandleTransientHttpError()

It is equivalent with the following:

Policy&lt;HttpResponseMessage&gt;
  .Handle&lt;HttpRequestException&gt;()
  .OrTransientHttpStatusCode()
  • The to-be-decorated function should return a HttpResponseMessage
  • It should trigger either for HttpRequestException
  • Or it should trigger if the status code is 408 or 5xx
.WaitAndRetryAsync(3, retryAttempt =&gt; TimeSpan.FromSeconds(retryAttempt));
  • It says that the to-be-decorated method is async
  • The retry policy should be used as a chosen resiliency action
  • With at most 3 retry attempts, with predefined sleep duration between attempts

If you are interested more about this, please check the following SO topics:

Execution

Depending on the policy definition you can either call Execute or ExecuteAsync. So, you have to know upfront what do you want to decorate and define your policy accordingly.

Polly also exposes methods like ExecuteAndCapture and ExecuteAndCaptureAsync. The different between these and the above ones is that the latter do not throw exception rather captures either the result of the method or the exception into a PolicyResult object.

Back to your example

Retrying the Task.Delay unconditionally is not supported by Polly. You have to have either a Handle&lt;&gt; or HandleResult&lt;&gt; to define a trigger. For the sake of simplicity I will cancel the Task.Delay which will throw OperationCanceledException and that would be our trigger.

var retry = Policy
	.Handle&lt;OperationCanceledException&gt;()
	.RetryAsync(3, (_, __) =&gt; Console.WriteLine(&quot;Retried&quot;));
await retry.ExecuteAsync(async () =&gt;
{
	 var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1));
	 await Task.Delay(2000, cts.Token);
});

I've added some logging to the policy for clarity.

Here you can find the related dotnet fiddle link.

huangapple
  • 本文由 发表于 2023年3月21日 02:01:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/75793775.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定