.net构造for while循环与超时

我通常使用while循环继续尝试某些操作,直到操作成功或超时已经过去:

bool success = false int elapsed = 0 while( ( !success ) && ( elapsed < 10000 ) ) { Thread.sleep( 1000 ); elapsed += 1000; success = ... some operation ... } 

我知道有几种方法可以实现这一点,但基本的一点是,我反复尝试一些操作,一直睡到成功,或者我睡得太久了。

是否有一个内置的.net类/方法/等来避免我在整个地方重写这个模式? 也许输入是一个Func(bool)和超时?

编辑
感谢所有贡献者。 我选择了sleep()方法,因为它是最不复杂的,我完全反复杂性=)这是我的(仍然需要测试)实现:

  public static bool RetryUntilSuccessOrTimeout( Func task , TimeSpan timeout , TimeSpan pause ) { if ( pause.TotalMilliseconds = 0 milliseconds" ); } var stopwatch = Stopwatch.StartNew(); do { if ( task() ) { return true; } Thread.Sleep( ( int )pause.TotalMilliseconds ); } while ( stopwatch.Elapsed < timeout ); return false; } 

您可以将算法包装在一个方法中:

 public bool RetryUntilSuccessOrTimeout(Func task, TimeSpan timeSpan) { bool success = false; int elapsed = 0; while ((!success) && (elapsed < timeSpan.TotalMilliseconds)) { Thread.Sleep(1000); elapsed += 1000; success = task(); } return success; } 

然后:

 if (RetryUntilSuccessOrTimeout(() => SomeTask(arg1, arg2), TimeSpan.FromSeconds(10))) { // the task succeeded } 

你可以使用SpinWait.SpinUntil

请参阅https://msdn.microsoft.com/en-us/library/dd449238(v=vs.110).aspx

bool spinUntil = System.Threading.SpinWait.SpinUntil(() => job.IsDisposed, TimeSpan.FromSeconds(5));

你真的不应该使用Sleep()等待任务完成。 完成任务后,您平均浪费500毫秒。

您应该能够使用任务并行库确定性地执行此操作,请参阅此处 。

此示例显示如何使用Wait方法或其在Task类中的等效方法等待单个任务。 它还说明了如何使用静态WaitAll和WaitAny方法等待多个任务。

我不知道有任何现有的东西,但我认为你可以创建一个接受超时和成功确定function的方法。 像这样的东西:

 public static bool KeepTrying(int timeout, Func operation) { bool success = false; int elapsed = 0; while ((!success) && (elapsed < timeout)) { Thread.Sleep(1000); elapsed += 1000; success = operation(); } return success; } 

或者你的函数可能更“强大”,你可以将它与灵活的参数结合起来:

 public bool KeepTrying(int timeout, Func operation, params object[] arguments) { bool success = false; int elapsed = 0; while ((!success) && (elapsed < timeout)) { Thread.Sleep(1000); elapsed += 1000; success = operation(arguments); } return success; } 

其他人提到了线程同步技术,这将允许您等到某个任务完成。 但是,如果你想像你一样继续轮询每一秒,你可以像这样包装那个方法:

 void Main() { Timeout(() => {return false;}); } public void Timeout(Func action, int timeout) { bool success = false; int elapsed = 0; while( ( !success ) && ( elapsed < timeout ) ) { Thread.Sleep( 1000 ); elapsed += 1000; success = action(); } Console.WriteLine("timed out."); } 

您可以抽象缩短代码并概括Timeout:

 int timer = 0; while (!SomeOperation(...) && Timeout(ref timer, 1000, 10000)); public bool Timeout(ref int timer, int increment, int maximum) { timer += increment; Thread.Sleep(increment); return timer < maximum; } 

第一种解决方案是使用SpinWait

 SpinWait.SpinUntil(() => LoopProcedure(), 1000); 

另一个解决方案是使用Task.Wait()

 var task = Task.Run(() => LoopProcedure()); task.Wait(1000); 

将循环包装到返回bool值的过程中

 private bool LoopProcedure() { bool success = false while( ( !success ) { // do some stuff ... } return success; } 

你需要使用Thread.Join 。 来自MSDN,

阻塞调用线程直到线程终止,同时继续执行标准COM和SendMessage抽取。

如果要等到指定的时间过去,则使用Thread.Join(TimeSpan)方法。 仅限.NET 3.0,3.5,4.0。

阻塞调用线程,直到线程终止或指定的时间过去 ,同时继续执行标准COM和SendMessage抽取。

本教程如何在C#中使用Threads将对您有所帮助。