Don’t Sleep

Have you programmed a multi-threaded application?

How many times have you wrote the following lines:

Thread t1 = new Thread(() => Console.WriteLine("Thread 1 working"));

 

t1.Start();

// do some work

Thread.Sleep(5000);

 

// continue execution

or this code snippet:

while (someArgument == true)

{

    Thread.Sleep(10);

}

 

If never – good for you!

The problem is that many programmers when confronted with the need to sync actions in different threads use a similar code construct.

Both code snippets shows a solution to a similar problem – wait until an action happens in another thread before continuing the current thread execution.

 

So I shouldn’t use Sleep?

No, there is nothing wrong with using Thread.Sleep when needed. However the examples above shows how it can been misused.

 

  • The 1st snippet shows Sleep as a way to wait till a thread has done some work and exited.
    Using Sleep introduce an unknown/random factor to your code.
    What happens if the created thread didn’t finish before the sleep – should we increase the wait time?
  • The 2nd snippet shows sleep as a way to sync two threads.
    Another thread change someArgument value an action has been performed. However CPU cycles are wasted checking the argument before each sleep.

 

There are better ways to solve those problems:

1. Use Thread.Join

2. EventWaitHandle

 

Thread.Join

We use Join when we want to wait till another thread ends.

Thread t1 = new Thread(() => Console.WriteLine("Thread 1 working"));

 

t1.Start();

// do some work

t1.Join();

// continue execution

No random results – a simple solution that always works.

EventWaitHandle

EventWaitHandle has very low CPU overhead and should can be to used to pause a thread until a signal is received.

static EventWaitHandle waitEventHandle = new AutoResetEvent(true);

public void DoWork()

{

    Console.WriteLine("Thread 1 working");

 

    // Do Some Work

 

    waitEventHandle.Set();

 

    // Do more Work

}

 

public void WaitThread()

{

    new Thread(DoWork).Start();

 

    waitEventHandle.WaitOne();

 

    //…

}

 

In this code snippet instead of using a loop and a shared variable we use AutoResetEvent so that WaitThreadthread can wait until DoWork thread signals.

 

Comment?