waiting

For quite some time I was using the old-fashioned way, using a while loop with a condition and timeout, to wait for an action to happen.

In other words, I was doing something like this:

public static bool WaitForAction(int timeoutInSeconds)
{
    var timeout = DateTime.Now.AddSeconds(timeoutInSeconds);
    while(!condition && DateTime.Now < timeout)
    {
        //usually throw an exception
        throw new Exception("Condition was not met.");
        //Depending on that your condition statement, it may
        //be required to refresh it (if not a method for example)
    }
}

This was until I discovered SpinWait.SpinUntil method from .NET framework and created a wrapper on top of it to be used in Selenium.

public static bool WaitForAction(Func<bool> condition, int timeoutInSeconds)
{
    return SpinWait.SpinUntil(condition, TimeSpan.FromSeconds(timeoutInSeconds));
}

It may not be much of a difference, but you have a more general way in dealing with stuff that you need to wait for.

Now, we all know that, in most cases, you won’t get much of an explanation from the Microsoft site, so let’s get a bit in more detail.

How SpinWait works

In its current implementation, SpinWait performs CPU-intensive spinning for 10 iterations before yielding. However, it doesn’t return to the caller immediately after each of those cycles: instead, it calls Thread.SpinWait to spin via the CLR (and ultimately the operating system) for a set time period. This time period is initially a few tens of nanoseconds, but doubles with each iteration until the 10 iterations are up. This ensures some predictability in the total time spent in the CPU-intensive spinning phase, which the CLR and operating system can tune according to conditions. Typically, it’s in the few-tens-of-microseconds region — small, but more than the cost of a context switch.

On a single-core machine (in this case could be a Virtual Machine runner for the Selenium tests), SpinWait yields on every iteration. You can test whether SpinWait will yield on the next spin via the property NextSpinWillYield.

If a SpinWait remains in “spin-yielding” mode for long enough (maybe 20 cycles) it will periodically sleep for a few milliseconds to further save resources and help other threads progress.

For more information on this, you can check J. Albahari’s blog.

So, in other words put, SpinWait limits the CPU-intensive spinning to a set number of iteration, after it yields its time slice on every spin (calling internally Thread.Yield and Thread.Sleep), lowering it’s resource consumption.