.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
其他人提到了线程同步技术,这将允许您等到某个任务完成。 但是,如果你想像你一样继续轮询每一秒,你可以像这样包装那个方法:
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将对您有所帮助。