While Haris's solution is an acceptable "quick fix," you have a major design flaw with your static method; the BackgroundWorker
class, being a Component
, implements IDisposable
, and therefore should be disposed at the end of its life.
The best way to recreate your pattern would be to manually invoke your work function on another thread. The only downside to this is that you must call Dispatcher.Invoke
to interact with anything on the UI thread while you are updating progress. Here's a sample of how you could do it.
using System.Threading;
public static void RunInThread<TProgress>(
Action<Action<TProgress>> worker,
Action<TProgress> updateProgress,
Action workerCompleted)
{
Thread workerThread = new Thread(() =>
{
worker(updateProgress);
workerCompleted();
});
workerThread.Start();
}
Because it's a generic method, you can use it to report any type of progress you like back. Here's an example of how you could call it:
RunInThread<double>(
updateProgress =>
{
Thread.Sleep(500);
updateProgress(0.5);
Thread.Sleep(500);
updateProgress(1);
},
progress =>
{
this.Dispatcher.Invoke(() =>
{
progressLabel.Text = progress.ToString();
});
},
() =>
{
this.Dispatcher.Invoke(() =>
{
progressLabel.Text = "Finished!";
});
}
);
You can also customize this method very easily to create overload that add ease when working with a single parameter or a return value.
public static void RunInThread<TProgress, TParameter>(
Action<Action<TProgress>, TParameter> worker,
Action<TProgress> updateProgress,
Action workerCompleted,
TParameter parameter)
{
Thread workerThread = new Thread(() =>
{
worker(updateProgress, parameter);
workerCompleted();
});
workerThread.Start();
}
public static void RunInThread<TProgress, TResult>(
Func<Action<TProgress>, TResult> worker,
Action<TProgress> updateProgress,
Action<TResult> workerCompleted)
{
Thread workerThread = new Thread(() =>
{
TResult result = worker(updateProgress);
workerCompleted(result);
});
workerThread.Start();
}
public static void RunInThread<TProgress, TParameter, TResult>(
Func<Action<TProgress>, TParameter, TResult> worker,
Action<TProgress> updateProgress,
Action<TResult> workerCompleted,
TParameter parameter)
{
Thread workerThread = new Thread(() =>
{
TResult result = worker(updateProgress, parameter);
workerCompleted(result);
});
workerThread.Start();
}
I would also recommend you add some error-handling code in case anything blows up within your work function, but I'll leave that exercise to you.