C# 如果出现某些错误,请在后台重新启动任务
我使用Mono.Mac(3.2.3)的一些REST请求与服务器通信,作为重试机制,我悄悄地尝试在HTTP操作失败或超时时进行多次尝试 我有以下几点:C# 如果出现某些错误,请在后台重新启动任务,c#,multithreading,task-parallel-library,C#,Multithreading,Task Parallel Library,我使用Mono.Mac(3.2.3)的一些REST请求与服务器通信,作为重试机制,我悄悄地尝试在HTTP操作失败或超时时进行多次尝试 我有以下几点: var tries = 0; while (tries <= ALLOWED_TRIES) { try { postTask.Start(); tries++; if (!postTask.Wait(Timeout)) { throw ne
var tries = 0;
while (tries <= ALLOWED_TRIES)
{
try
{
postTask.Start();
tries++;
if (!postTask.Wait(Timeout))
{
throw new TimeoutException("Operation timed out");
}
break;
} catch (Exception e) {
if (tries > ALLOWED_TRIES)
{
throw new Exception("Failed to access Resource.", e);
}
}
}
var=0;
while(允许的尝试次数)
{
抛出新异常(“无法访问资源。”,e);
}
}
}
其中任务使用父方法的参数,如下所示
var postTask = new Task<HttpWebResponse>(() => {return someStuff(foo, bar);},
Task.Factory.CancellationToken,
Task.Factory.CreationOptions);
var postTask=newtask(()=>{returnsomething(foo,bar);},
Task.Factory.CancellationToken,
任务、工厂、创作选项);
问题似乎是,任务在第一次完成(以及随后的失败)后,不希望使用
postTask.Start()
再次运行该任务。有没有一种简单的方法可以做到这一点,或者我是否以这种方式滥用了任务?是否有某种方法可以将任务重置为初始状态,或者我最好使用某种工厂?您在这里确实误用了任务,原因如下:
- 同一任务不能运行多次。当它完成时,它就完成了
- 不建议手动构造
Task
对象,有Task.Run
和Task.Factory.Start
- 对于执行IO绑定工作的任务,不应使用
Task.Run
/Task.Factory.Start
。它们用于CPU限制的工作,因为它们从ThreadPool
中“借用”线程来执行任务操作。相反,使用基于纯异步任务的API来实现这一点,它不需要专门的线程来完成
例如,在下面,您可以从UI线程调用GetResponseWithRetryAsync
,并保持UI响应:
async Task<HttpWebResponse> 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);
}
}
}
async任务GetResponseWithRetryAsync(字符串url,int重试)
{
如果(重试次数<0)
抛出新ArgumentOutOfRangeException();
var request=WebRequest.Create(url);
while(true)
{
尝试
{
var result=wait request.GetResponseAsync();
返回(HttpWebResponse)结果;
}
捕获(例外情况除外)
{
如果(--retries==0)
throw;//重新显示上一个错误
//否则,请记录错误并重试
Debug.Print(“错误后重试:+ex.Message”);
}
}
}
更多阅读:
.我建议您这样做:
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的重试模式设计。你可以在这里查看:这假设是C#5.0,从这个问题上我不清楚这是一个选项。@svick,同样可以通过ContinueWith
回调来完成,尽管代码没有那么可读性。@svick,这里有一个,作为我的学习练习,我已经学会了更爱async/await
。为了获得提示和“理论”组件,我将给出答案,但需要注意的是,扩展问题(与.NET 4兼容)中提供的答案是我衍生解决方案的来源。感谢您的努力,非常感谢。丹尼尔帕克,很高兴它起了作用。