如果发生某些错误,则在后台重新启动任务

我正在使用一些使用Mono.Mac(3.2.3)的REST请求与服务器通信,作为重试机制,我正在悄悄地尝试在HTTP操作失败或超时的情况下多次尝试。

我有以下几点;

var tries = 0; while (tries  ALLOWED_TRIES) { throw new Exception("Failed to access Resource.", e); } } } 

任务使用父方法的参数如此;

 var postTask = new Task(() => {return someStuff(foo, bar);}, Task.Factory.CancellationToken, Task.Factory.CreationOptions); 

问题似乎是任务不希望在第一次完成(以及后续失败)后使用postTask.Start()再次运行。 有没有一种简单的方法可以做到这一点,还是我以这种方式滥用任务? 是否有某种方法将任务重置为初始状态,或者我最好使用某种工厂?

你确实在这里滥用了这个Task ,原因如下:

  • 您不能多次运行相同的任务。 完成后,就完成了。

  • 不建议手动构造Task对象,有Task.RunTask.Factory.Start

  • 您不应该将Task.Run / Task.Factory.Start用于执行IO绑定工作的任务。 它们用于CPU绑定工作,因为它们从ThreadPool “借用”一个线程来执行任务操作。 相反,为此使用纯异步的基于Task的API,不需要专用线程来完成。

例如,下面您可以从UI线程调用GetResponseWithRetryAsync并仍然保持UI响应:

 async Task GetResponseWithRetryAsync(string url, int retries) { if (retries < 0) throw new ArgumentOutOfRangeException(); var request = WebRequest.Create(url); while (true) { try { var result = await request.GetResponseAsync(); return (HttpWebResponse)result; } catch (Exception ex) { if (--retries == 0) throw; // rethrow last error // otherwise, log the error and retry Debug.Print("Retrying after error: " + ex.Message); } } } 

更多阅读:

“Task.Factory.StartNew”vs“new Task(...)。Start” 。

Task.Run与Task.Factory.StartNew 。

我建议做这样的事情:

 private int retryCount = 3; ... public async Task OperationWithBasicRetryAsync() { int currentRetry = 0; for (; ;) { try { // Calling external service. await TransientOperationAsync(); // Return or break. break; } catch (Exception ex) { Trace.TraceError("Operation Exception"); currentRetry++; // Check if the exception thrown was a transient exception // based on the logic in the error detection strategy. // Determine whether to retry the operation, as well as how // long to wait, based on the retry strategy. if (currentRetry > this.retryCount || !IsTransient(ex)) { // If this is not a transient error // or we should not retry re-throw the exception. throw; } } // Wait to retry the operation. // Consider calculating an exponential delay here and // using a strategy best suited for the operation and fault. Await.Task.Delay(); } } // Async method that wraps a call to a remote service (details not shown). private async Task TransientOperationAsync() { ... } 

此代码来自Microsoft的重试模式设计。 你可以在这里查看: https : //msdn.microsoft.com/en-us/library/dn589788.aspx