Reputation: 17831
I want to start a BackgroundWorker
after another one is completed. I'm not sure on how to write the code for it, so I don't really have anything to show.
I thought about writing it in the RunWorkerCompleted
, but that seems like the wrong place to put logic for starting another worker.
Where and how should I do this?
Basically, I want to use the same worker, but to do something else. Like in step 1 it parses data from files and in step 2, after step 1 is completed, it should write the parsed data from memory to the database.
Upvotes: 5
Views: 4511
Reputation: 231
This will allow to use one background worker for multiple and sequental operations:
private void DoBackgroundWork<T>(string name, Func<T> work, Action<T> onComplete)
{
lblCurrentOperation.Text = name;
StaticClass.OnProgress = (p) => backgroundWorker1.ReportProgress(p);
T result = default(T);
var handler = new DoWorkEventHandler((s, e) =>
{
result = work();
});
backgroundWorker1.DoWork += handler;
RunWorkerCompletedEventHandler completedHandler = null;
completedHandler = new RunWorkerCompletedEventHandler((s, e) =>
{
onComplete(result);
backgroundWorker1.DoWork -= handler;
backgroundWorker1.RunWorkerCompleted -= completedHandler;
lblCurrentOperation.Text = string.Empty;
progressBar1.Value = 0;
});
backgroundWorker1.RunWorkerCompleted += completedHandler;
}
usage:
DoBackgroundWork("Loading resources",
() =>
{
return DoWork();
},
(result) =>
{
//final UI operations
Task.Delay(500).ContinueWith(t => this.Invoke((Delegate)new Action(() => anotherOperationWithSameWorker())));
});
backgroundWorker1.RunWorkerAsync();
Upvotes: 0
Reputation: 57658
From your description it seems that the steps are related and sequential so I would implement it as a single BGW where the DoWork
performs both steps with a call to ReportProgress
between the parsing step and the write to the database step.
You can then handle the ProgressChanged
event that runs on the UI thread to perform any logic after the parsing step as finished, knowing that the worker is already writing to the database.
The ReportProgress
accepts an integer to identify the percentage completed of the background task and an optionally custom object. So in your ProgressChanged
handler you need to have logic to interpret this progress information. In this case, being a two stepped job, you can just call ReportProgress(50)
.
Upvotes: 3
Reputation: 1564
If using a third party library for job scheduling is acceptable for you check out Quartz.NET and it's job listener mechanism described here http://quartznet.sourceforge.net/tutorial/lesson_7.html. If you want to implement it by yourself i'd use a single BackgroundWorker
that would execute a set of jobs organised into a Chain of Responsibility, you can read more about this pattern here http://dofactory.com/Patterns/PatternChain.aspx.
Upvotes: 1
Reputation: 133975
It's probably best to use two different BackgroundWorker
components. Start the second one in the RunWorkerCompleted
event handler for the first one. That seems like a very reasonable way to do things. Just don't try to do it with a single BackgroundWorker
.
As Tudor mentioned, you could use Task
, but then you lose the convenience of BackgroundWorker
, with its familiar event-oriented interface, progress reporting, and such.
Upvotes: 3
Reputation: 62439
You can instead use the .NET 4.0 Task class and then queue more work using Task.ContinueWith.
Upvotes: 4