C# 如何异步重试直到成功或超时?
我写下了以下几行代码:C# 如何异步重试直到成功或超时?,c#,multithreading,task,C#,Multithreading,Task,我写下了以下几行代码: public static bool RetryUntilSuccessOrTimeoutAsync(Func<bool> task, TimeSpan executionTimeout, CancellationToken? token = null) { var data = new ExecutionContextData(task, executionTimeout, token); var nonBlockingT
public static bool RetryUntilSuccessOrTimeoutAsync(Func<bool> task,
TimeSpan executionTimeout, CancellationToken? token = null) {
var data = new ExecutionContextData(task, executionTimeout, token);
var nonBlockingTask = new Task<bool>(SyncTaskExecutor, data);
nonBlockingTask.Start();
var result = nonBlockingTask.ContinueWith(t => t.Result);
return result.Result;
}
class ExecutionContextData {
private readonly Func<bool> task;
private readonly TimeSpan executionTimeout;
private readonly CancellationToken? cancellationToken;
public ExecutionContextData(Func<bool> task, TimeSpan executionTimeout, CancellationToken? cancellationToken) {
this.cancellationToken = cancellationToken;
this.executionTimeout = executionTimeout;
this.task = task;
}
public Func<bool> Task {
get { return task; }
}
public TimeSpan ExecutionTimeout {
get { return executionTimeout; }
}
public CancellationToken? CancellationToken {
get { return cancellationToken; }
}
}
private static bool SyncTaskExecutor(object executionHelper) {
var context = executionHelper as ExecutionContextData;
Task<bool> newTask =
context.CancellationToken.HasValue ? new Task<bool>(ExecuteTask, context.Task, context.CancellationToken.Value)
: new Task<bool>(ExecuteTask, context.Task);
newTask.Start();
bool timeoutResult = newTask.Wait(context.ExecutionTimeout);
if (timeoutResult)
return newTask.Result;
return false;
}
public static bool retryuntillsuccessortimeoutasync(Func任务,
TimeSpan executionTimeout,CancellationToken?token=null){
var data=新的ExecutionContextData(任务、executionTimeout、令牌);
var nonBlockingTask=新任务(SyncTaskExecutor,数据);
nonBlockingTask.Start();
var result=nonBlockingTask.ContinueWith(t=>t.result);
返回结果。结果;
}
类ExecutionContextData{
私有只读Func任务;
私有只读TimeSpan executionTimeout;
私有只读CancellationToken?CancellationToken;
public ExecutionContextData(Func任务、TimeSpan executionTimeout、CancellationToken?CancellationToken){
this.cancellationToken=cancellationToken;
this.executionTimeout=executionTimeout;
this.task=任务;
}
公共职能任务{
获取{return task;}
}
公共时间跨度执行超时{
获取{return executionTimeout;}
}
公共取消令牌?取消令牌{
获取{return cancellationToken;}
}
}
专用静态布尔SyncTaskExecutor(对象executionHelper){
var context=executionHelper作为ExecutionContextData;
任务任务=
context.CancellationToken.HasValue?新任务(ExecuteTask,context.Task,context.CancellationToken.Value)
:新任务(ExecuteTask,context.Task);
newTask.Start();
bool timeoutResult=newTask.Wait(context.ExecutionTimeout);
如果(超时结果)
返回newTask.Result;
返回false;
}
但据我所知,结果属性调用将阻止调用方。所以,我很不明白如何完成这项任务:
“如何异步执行任务,因此如果超过超时时间,它将返回false或返回任务的结果,该结果应反复执行?”如果您有要取消或超时的操作,为什么不尝试类似的操作:
public static class Retries
{
public enum Result
{
Success,
Timeout,
Canceled,
}
public static Task<Result> RetryUntilTimedOutOrCanceled(this Func<bool> func, CancellationToken cancel, TimeSpan timeOut)
{
return Task.Factory.StartNew(() =>
{
var start = DateTime.UtcNow;
var end = start + timeOut;
while (true)
{
var now = DateTime.UtcNow;
if (end < now)
return Result.Timeout;
var curTimeOut = end - now;
Task<bool> curTask = null;
try
{
if (cancel.IsCancellationRequested)
return Result.Canceled;
curTask = Task.Factory.StartNew(func, cancel);
curTask.Wait((int)curTimeOut.TotalMilliseconds, cancel);
if (curTask.IsCanceled)
return Result.Canceled;
if (curTask.Result == true)
return Result.Success;
}
catch (TimeoutException)
{
return Result.Timeout;
}
catch (TaskCanceledException)
{
return Result.Canceled;
}
catch (OperationCanceledException)
{
return Result.Canceled;
}
}
});
}
}
class Program
{
static void Main(string[] args)
{
var cancelSource = new CancellationTokenSource();
Func<bool> AllwaysFalse = () => false;
Func<bool> AllwaysTrue = () => true;
var result = AllwaysFalse.RetryUntilTimedOutOrCanceled(cancelSource.Token, TimeSpan.FromSeconds(3)).Result;
Console.WriteLine(result);
result = AllwaysTrue.RetryUntilTimedOutOrCanceled(cancelSource.Token, TimeSpan.FromSeconds(3)).Result;
Console.WriteLine(result);
var rTask = AllwaysFalse.RetryUntilTimedOutOrCanceled(cancelSource.Token, TimeSpan.FromSeconds(100));
System.Threading.Thread.Sleep(1000);
cancelSource.Cancel();
result = rTask.Result;
Console.WriteLine(result);
Console.ReadLine();
}
}
公共静态类重试
{
公共枚举结果
{
成功,,
超时,
取消,
}
公共静态任务RetryUntiltimedOutorCancelled(此函数,CancellationToken取消,TimeSpan超时)
{
返回Task.Factory.StartNew(()=>
{
var start=DateTime.UtcNow;
var end=开始+超时;
while(true)
{
var now=DateTime.UtcNow;
如果(结束<现在)
返回结果。超时;
var curTimeOut=结束-现在;
Task-curTask=null;
尝试
{
如果(取消。已请求取消安装)
返回结果。已取消;
curTask=Task.Factory.StartNew(func,cancel);
Wait((int)curTimeOut.total毫秒,取消);
如果(已取消curTask.IsCanceled)
返回结果。已取消;
if(curTask.Result==true)
回报结果。成功;
}
捕获(超时异常)
{
返回结果。超时;
}
捕获(TaskCanceledException)
{
返回结果。已取消;
}
捕获(操作取消异常)
{
返回结果。已取消;
}
}
});
}
}
班级计划
{
静态void Main(字符串[]参数)
{
var cancelSource=new CancellationTokenSource();
Func AllwaysFalse=()=>false;
Func AllwaysTrue=()=>true;
var结果=AllwaysFalse.RetryUntilTimedOutOrCanceled(cancelSource.Token,TimeSpan.FromSeconds(3)).result;
控制台写入线(结果);
结果=AllwaysTrue.RetryUntiltimedOut或Canceled(cancelSource.Token,TimeSpan.FromSeconds(3))。结果;
控制台写入线(结果);
var rTask=AllwaysFalse.RetryUntilTimedOutOrCanceled(cancelSource.Token,TimeSpan.FromSeconds(100));
系统线程线程睡眠(1000);
cancelSource.Cancel();
结果=rTask.result;
控制台写入线(结果);
Console.ReadLine();
}
}