I have written a class that uses a worker thread and it utilises an event object. I have cut the class down to the basics:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Threading;
using System.Windows.Forms;
namespace TEST
{
public class TEST_Worker
{
public static ManualResetEvent m_Event = new ManualResetEvent(false);
private BackgroundWorker m_backgroundWorker;
public TEST_Worker()
{
InitBackgroundWorker();
}
private void InitBackgroundWorker()
{
m_backgroundWorker = new BackgroundWorker();
m_backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
m_backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);
m_backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
m_backgroundWorker.WorkerReportsProgress = true;
}
public void start()
{
m_Event.Reset();
m_backgroundWorker.RunWorkerAsync();
}
public void stop()
{
m_backgroundWorker.CancelAsync();
}
public void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
m_backgroundWorker.ReportProgress(100, "Progress {0}%");
}
// This event handler updates the UI
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
}
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
m_Event.Set();
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// dispose managed resources
m_backgroundWorker.Dispose();
}
// free native resources
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
In the form class (a menu item handler) I am doing this:
private void testToolStripMenuItem_Click(object sender, EventArgs e)
{
TEST.TEST_Worker myTest = new TEST.TEST_Worker();
myTest.start();
TEST.TEST_Worker.m_Event.WaitOne();
MessageBox.Show("Complete!");
}
I don't have it right. The form needs to not sleep or anything (else the GUI will not get updated - real code does progress bar updates). But, I also want the form to know when the thread has finished and then perform a task. At the moment it just carries on after the call to start
.
Clearly I am not using the ManualResetEvent
in the right way. At the moment my application just hangs indefinitely. It never shows the message box (I don't want the thread to show it - but the form).
Does this make sense? Am I going about this the wrong way?
I have used it before, but admittedly it was when a worker thread was required to wait for a sub-worker thread to finish before it carried on. This context is different, a form calling a worker thread and then wanting to do something when the thread has finished (but not choke the form for GUI updates).