F.P
F.P

Reputation: 17831

Run BackgroundWorker after another one completed

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

Answers (5)

Anton Dremin
Anton Dremin

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

Jo&#227;o Angelo
Jo&#227;o Angelo

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

dmusial
dmusial

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

Jim Mischel
Jim Mischel

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

Tudor
Tudor

Reputation: 62439

You can instead use the .NET 4.0 Task class and then queue more work using Task.ContinueWith.

Upvotes: 4

Related Questions