.net construct for while loop with timeout

纵然是瞬间 提交于 2019-12-03 22:29:06

You could wrap your algorithm in a method:

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

and then:

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

You could use SpinWait.SpinUntil

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

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

You really should not have to use Sleep() to wait for tasks to complete. You waste an average of 500ms after the task has completed by doing this.

You ought to be able to do this deterministically using Task Parallel Library, see here for example.

This example shows how to use the Wait method, or its equivalent in the Task class, to wait on a single task. It also shows how to use the static WaitAll and WaitAny methods to wait on multiple tasks.

I don't know that there's any existing thing, but I would think you could create a method to that would accept the timeout and the success-determination function. Something like this:

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

or maybe your Function could be more "robust" and you could couple it with flexible arguments:

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

Others have mentioned thread synchronization techniques, which would allow you to wait until some task is finished. However, if you want to continue polling every second like you are doing, you can wrap that method like this:

void Main()
{
    Timeout(() => {return false;});
}

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

You can abstract shorten your code a bit and generalize the 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;
}

The first solution is to use SpinWait

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

The other solution is to use Task.Wait()

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

Wrap your loop into a procedure that return bool value

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

You need to use Thread.Join. From MSDN,

Blocks the calling thread until a thread terminates, while continuing to perform standard COM and SendMessage pumping.

If you want to wait until a specified time elapses, then use the Thread.Join (TimeSpan) method. .NET 3.0, 3.5, 4.0 only.

Blocks the calling thread until a thread terminates or the specified time elapses, while continuing to perform standard COM and SendMessage pumping.

This tutorial on how to use Threads in C# will help you.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!