重试之前的任务操作 TPL [英] Retry previous task action TPL

查看:21
本文介绍了重试之前的任务操作 TPL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想实现一个重试任务,该任务执行之前失败的任务操作并重复它.

I'd like to implement a retry task that takes the previous failing tasks action and repeat it.

这是我目前所拥有的.然而,它只是重复了任务出错的事实,而不是真正再次触发任务的动作.

This is what I have so far. However it just repeats the fact that the task is in fault rather than actually firing the action of the task again.

public static async Task<T> Retry<T>(this Task<T> task, int retryCount, int delay, TaskCompletionSource<T> tcs = null)
{
    if (tcs == null)
    {
        tcs = new TaskCompletionSource<T>();
    }

    await task.ContinueWith(async _original =>
    {
        if (_original.IsFaulted)
        {
            if (retryCount == 0)
            {
                tcs.SetException(_original.Exception.InnerExceptions);
            }
            else
            {
                Console.WriteLine("Unhandled exception. Retrying...");

                await Task.Delay(delay).ContinueWith(async t =>
                {
                    await Retry(task, retryCount - 1, delay, tcs);
                });
            }
        }
        else
            tcs.SetResult(_original.Result);
    });
    return await tcs.Task;
}

我试图通过一点反思来获得行动.然而,似乎一旦任务完成,动作就会被设置为空.

I tried to get the action with a little reflection. However it seems that once the task is completed the action is set to null.

var action = task
    .GetType()
    .GetField("m_action", BindingFlags.NonPublic | BindingFlags.Instance)
    .GetValue(task) as Action;

理想情况下,我希望我的实现如下所示:

Ideally I would like my implementation to look like this:

try
{
    await MakeFailure().Retry(5, 1000);
}
catch (Exception ex)
{
    Console.WriteLine("I had an exception");
}

这可能是不可能的,但我想在将代码重构为 Retry(Func task)

This may not be possible but I'd like to make sure before refactoring the code to a Retry(Func<T> task)

推荐答案

并不完全反对.但它将代码流更改为我不喜欢的错误优先布局

Not completely against it. But it changes the flow of the code to a fault first layout which I don't like

考虑您的类型.Task 代表一个异步操作.在异步世界中,Task 代表一个异步操作已经开始.Task 不是你可以重试"的.

Consider your types. Task represents an asynchronous operation. In the asynchronous world, Task represents an asynchronous operation that has already started. Task is not something you can "retry".

另一方面,Func 表示可以启动的异步操作.或者重新启动.这就是您需要处理的内容.

On the other hand, Func<Task> represents an asynchronous operation that can be started. Or restarted. That's what you need to work with.

使用适当的类型后,代码很简单:

Once you are using the appropriate type, the code is straightforward:

public static async Task<T> Retry<T>(Func<Task<T>> action, int retryCount, int delay)
{
  while (retryCount > 0)
  {
    try
    {
      return await action().ConfigureAwait(false);
    }
    catch (Exception ex)
    {
      await Task.Delay(delay).ConfigureAwait(false);
      --retryCount;
    }
  }
  return await action().ConfigureAwait(false);
}

像其他回答者一样,我建议您使用实际为此设计的库.瞬态故障处理应用程序块Polly 就是两个很好的例子.

Like the other answerer, I recommend you use a library that was actually designed for this. The Transient Fault Handling Application Block and Polly are two good examples.

这篇关于重试之前的任务操作 TPL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆