Social Icons

twitter google plus linkedin rss feed

Pages

3.10.12

A Thread.Sleep that does not freeze the thread

I have been trying to add unit tests to my SharePoint code and it’s not an easy task. One of the main points I wanted to test was the ItemEventReceivers on a list. This works if you use the synchronous events such as ItemAdding or ItemUpdating but when it comes to test if the asynchronous events have taken place as expected you need to wait a bit.

Putting the test thread to sleep prevents the asynchronous events from happening (it’s on the same thread as the SharePoint code) and, even though your code is working when you are executing it manually, all of the tests fail so I have created a new class based on timers that will let the asynchronous events to trigger and execute. I call it Waiter.
public class Waiter : IDisposable
{
    public enum WaiterState
    {
        Waiting,
        TimedOut,
        Success,
        Error
    };

    System.Timers.Timer WaitTimer;
    ManualResetEvent manualResetEvent;
    int WaitCounter;

    private Waiter(int interval)
    {
        WaitCounter = 0;

        manualResetEvent = new ManualResetEvent(true);
        WaitTimer = new System.Timers.Timer() { AutoReset = false, Interval = interval };
        WaitTimer.Elapsed += new ElapsedEventHandler(WaitTimer_Elapsed);
    }

    void WaitTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        WaitCounter++;
        manualResetEvent.Set();
    }

    /// 
    /// Waits for the interval in milliseconds times number of times or once by default.
    /// 
    public static WaiterState Wait(int interval, int times)
    {
        try
        {
            using (Waiter WaiterClass = new Waiter(interval))
            {
                while (WaiterClass.WaitCounter <= times)
                {
                    WaiterClass.WaitTimer.Start();
                    WaiterClass.manualResetEvent.WaitOne();
                }
            }
        }
        catch
        {
            return WaiterState.Error;
        }

        return WaiterState.Success;
    }

    /// 
    /// Waits for the interval in milliseconds once.
    /// 
    public static WaiterState Wait(int interval)
    {
        return Wait(interval, 0);
    }

    void Dispose()
    {
        WaitTimer.Dispose();
    }
}
Give it a go.