【问题标题】:How to run a Task N times until it succeeds?如何运行任务 N 次直到成功?
【发布时间】:2023-03-16 06:19:01
【问题描述】:

我正在使用 ContinueWith 函数处理 C# 的 TaskFactory。这个问题正在尝试解决它

  • 执行 Foo()。
  • 如果结果成功,退出
  • 如果 Foo() 没有成功,则迭代并执行 Foo() 直到成功(最大迭代 3 次)
  • 如果3次迭代都不成功,放弃

我开始的代码是这样的

var executeTask = Task.Factory.StartNew<ExecutionStatus>(() =>
        {
            return Foo();
        });
        executeTask.ContinueWith(task => CheckIfExecutionWasSuccessful(task)).
                        ContinueWith(task => CheckIfExecutionWasSuccessful(task)).
                        ContinueWith(task => CheckIfExecutionWasSuccessful(task)).
                        ContinueWith(task => CheckLastTimeBeforeGivingUp(task));

Foo() 和 CheckIfExecutionWasSuccessful() 看起来像这样

ExecutionStatus Foo(){
      //Do my work
      return new ExecutionStatus(){Succeded = true}
     }

ExecutionStatus CheckIfExecutionWasSuccessful(Task<ExecutionStatus> task){
            if(task.Result.Succeeded) return task.Result;
            else return Foo()

有些事情告诉我,这不是解决这个问题的最佳方法。有什么建议和想法吗?

【问题讨论】:

  • 你在使用 >=.net45 吗?如果是这样,你真的应该去async/await而不是使用.ContinueWith
  • 我们在 .NET 4.0 上,我没有将其更改为 4.5 的奢侈。不过我很好奇,如果我使用 async/await,我会怎么做
  • 你可以使用一个简单的循环和 async/await
  • 基本上,您的问题是使用两年前的技术解决的问题。您的代码会大大简化。
  • 检查thisthis

标签: c# task-parallel-library task


【解决方案1】:

我不明白你为什么要通过使用多个 Tasks 和 ContinueWith() 来使事情变得更复杂。相反,编写代码就像没有Tasks 和然后Task 中运行它:

Task.Factory.StartNew(() =>
{
    for (int i = 0; i < maxTries - 1; i++)
    {
        try
        {
            return Foo();
        }
        catch
        { }
    }

    return Foo();
});

这使得代码更清晰,更明显正确,更容易修改。

【讨论】:

  • 如果所有尝试都失败,这应该传播异常,而不是指示成功。
  • @Servy 会的,这就是为什么最后一次调用 Foo() 不在尝试范围内。
【解决方案2】:

简单:

var MaxTries = 3;
var executeTask = Task.Factory.StartNew<ExecutionStatus>(() => Foo());

for(var i = 0; i < MaxTries; i++)
{
    executeTask = executeTask.ContinueWith(task => CheckIfExecutionWasSuccessful(task));
}

executeTask = executeTask.ContinueWith(task => CheckLastTimeBeforeGivingUp(task));

【讨论】:

  • 但是这不管任务成功与否都要执行3次CheckIfExecutionWasSuccesful(),不是吗?
  • 绝对可以,如果 CheckIfExecutionWasSuccessful 是一个昂贵的调用。我并不是说在我的情况下是这样,我只是想找出最好的方法
猜你喜欢
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多