I am writing a library that communicates with several WCF endpoints. In many cases, I have to wait for a particular state or condition on the remote service. I have written a simple polling wait loop which looks something like this:
private bool WaitForTrue(Func<bool> action, TimeSpan waitTime, TimeSpan checkInterval)
{
DateTime end = DateTime.UtcNow + waitTime;
while (DateTime.UtcNow < end)
{
if (action())
{
return true;
}
Thread.Sleep(checkInterval);
}
return action();
}
After reading several posts about how Thread.Sleep
is a sign of a poorly designed program, I'm reevaluating every place I've used it. I'm struggling with the best way to replace its usage in this wait loop. I've seen recommendations to use Task.Delay
, but since I have to block execution I think I would have to use Task.Delay(checkInterval).Wait()
which doesn't seem to provide the typical advantages of tasks.
I'm aware of the advantages of using a callback/event-based WCF method, rather than polling, but unfortunately I am unable to modify the service endpoints to expose this kind of functionality.
My library does not make use of any multi-threading, but I would like it to be friendly to consumers that may wish to multi-thread their applications.
Is replacing Thread.Sleep
with Task.Delay.Wait()
the way to go, or are there better ways to implement a blocking wait loop?
Since you can't be notified by the service when the event that you are looking for happens polling is the best you can do.
If you have a lot of these polling loops running at the same time consider using async waiting to release threads. That requires using, for example,
await Task.Delay(...);
and making the polling method and the entire call chain async.
This is a waste of dev time if there are just a few such polling loops.
Sleeping is fine for purposes of timing which you are doing here.