如果发生某些错误,则在后台重新启动任务
我正在使用一些使用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.Run
和Task.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