Pausing background thread with AutoResetEvent.WaitOne() and .Set()

Crazywako picture Crazywako · Apr 14, 2013 · Viewed 8.1k times · Source

I have following code. I'm trying to make buttons to main Form which can Pause, Continue and Stop the background thread the downloader is running on (private Thread thread)

Form1.cs

private AutoResetEvent waitHandle = new AutoResetEvent(true);
private Thread thread;

        private void ThreadJob()
        {
            Downloader download = new Downloader();
            download.runDownloader();
        }

        // THREADS button1 is "Download now"-button
        private void button1_Click(object sender, EventArgs e)
        {
            ThreadStart job = new ThreadStart(ThreadJob);
            thread = new Thread(job);
            thread.IsBackground = true;
            thread.Start();
        }

This code is ran on Windows Form. I have buttons for all those actions (Pause, Continue, Stop)

Pause and continue button has code on form

private void btnPause_Click(object sender, EventArgs e)
{
    waitHandle.WaitOne(); // Need to pause the background thread
}

 private void btnContinue_Click(object sender, EventArgs e)
    {
        waitHandle.Set(); // Need to continue the background thread
    }

The problem is pressing Pause button will freeze the main Form not the background thread.

Answer

Matthew Watson picture Matthew Watson · Apr 14, 2013

It is runDownloader() that must be able to pause.

It will need to periodically call waitHandle.WaitOne() on the wait handle.

Your WaitHandle must be a ManualResetEvent, not an AutoResetEvent and you should initialise it so that it is signalled (unless you want to start your thread in a "paused" state).

You will also have to change your button handlers as follows:

private void btnPause_Click(object sender, EventArgs e)
{
    waitHandle.Reset(); // Need to pause the background thread
}

private void btnContinue_Click(object sender, EventArgs e)
{
    waitHandle.Set(); // Need to continue the background thread
}

This means that you must be able to pass waitHandle to the thread so that it can wait on it.

However, there are better ways of managing thread cancellation since .Net 4, namely the use of CancellationTokenSource and CancellationToken.

See this Microsoft article for details.