Using BackgroundWorker
I’ve decided to take a deeper look at all available multi-threading options in .net 4.5. One of the simpler options is the BackgroundWorker. To investigate, I’ve setup a simple BackgroundWorker with progress and completion reporting.
using System;
using System.ComponentModel;
using System.Threading;
namespace TestBackgroundWorker
{
class TestBkGrdWorker
{
static void LogMsg(string msg, params object[] args)
{
Console.Out.Write("{0} ThreadId={1} ",
DateTime.Now.ToString("HH:MM:ss.fff"),
Thread.CurrentThread.ManagedThreadId);
Console.Out.WriteLine(msg, args);
}
// RunTest
//
// Function run by main thread
// Main thread sets up the background worker instance
// and fires it off
public void RunTest()
{
BackgroundWorker bkWorker = new BackgroundWorker();
bkWorker.WorkerReportsProgress = true;
// setup functions the background worker calls
// to do work, report progress, and to report completion
bkWorker.DoWork += bkWorker_DoWork;
bkWorker.ProgressChanged += bkWorker_ProgressChanged;
bkWorker.RunWorkerCompleted += bkWorker_RunWorkerCompleted;
AutoResetEvent myFlag = new AutoResetEvent(false);
// trigger background worker to run async
bkWorker.RunWorkerAsync(myFlag);
LogMsg("Main thread working, BackgroundWorker busy={0}",
bkWorker.IsBusy);
myFlag.WaitOne(); // wait for someone to signal this flag
LogMsg("RunTest thread resumes control upon completion of background thread");
}
// bkWorker_ProgressChanged
//
// Report progress
void bkWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
LogMsg("Background worker update progress, {0:00.0}% done",
e.ProgressPercentage);
}
// bkWorker_RunWorkerCompleted
//
// Report work is completed
void bkWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
LogMsg("Background worker completed");
}
// bkWorker_DoWork
//
// Function run by background worker.
// Random work method that takes an arbitrarily set 2 seconds
// to complete, with a progress report every 200ms.
void bkWorker_DoWork(object sender, DoWorkEventArgs e)
{
LogMsg("Background worker starting");
float percentDone = 0.0f;
for (int i = 0; i < 10; i++)
{
Thread.Sleep(200);
percentDone += 10.0f;
BackgroundWorker bkwkr = sender as BackgroundWorker;
if (bkwkr != null)
{
bkwkr.ReportProgress((int)percentDone);
}
}
LogMsg("Background worker completed");
AutoResetEvent myFlag = e.Argument as AutoResetEvent;
if (myFlag != null)
{
myFlag.Set();
}
}
// Main
// Start up a background worker test instance
static void Main(string[] args)
{
TestBkGrdWorker testWkr = new TestBkGrdWorker();
testWkr.RunTest();
}
}
}
18:05:51.835 ThreadId=3 Background worker starting
18:05:51.805 ThreadId=1 Main thread working, BackgroundWorker busy=True
18:05:52.107 ThreadId=4 Background worker update progress, 10.0% done
18:05:52.287 ThreadId=4 Background worker update progress, 20.0% done
18:05:52.487 ThreadId=4 Background worker update progress, 30.0% done
18:05:52.687 ThreadId=4 Background worker update progress, 40.0% done
18:05:52.889 ThreadId=4 Background worker update progress, 50.0% done
18:05:53.091 ThreadId=4 Background worker update progress, 60.0% done
18:05:53.291 ThreadId=4 Background worker update progress, 70.0% done
18:05:53.493 ThreadId=4 Background worker update progress, 80.0% done
18:05:53.693 ThreadId=4 Background worker update progress, 90.0% done
18:05:53.893 ThreadId=4 Background worker update progress, 100.0% done
18:05:53.893 ThreadId=3 Background worker completed
18:05:53.903 ThreadId=1 RunTest thread resumes control upon completion of background thread