Marc
Marc

Reputation: 9282

Restart background worker

Is there a way to directly "restart" a background worker? Calling CancelAsync() followed by RunWorkerAsync() clearly won't do it as their names imply.

Background info: I have a background worker which calculates a total in my .net 2.0 Windows Forms app. Whenever the user modifies any value which is part of this total I'd like to restart the background worker in case it would be running so that directly the latest values are considered.

Upvotes: 5

Views: 17925

Answers (5)

Jannick Breunis
Jannick Breunis

Reputation: 343

May this method help someone... I've created a function to reset the backgroundworker in one method. I use it for task to do periodically.

By creating a Task, the backgroundworker is can be stopped with the CancelAsync and restarted inside the Task. Not making a Task wil start the backgroundworker again before it is cancelled, as the OP describes.

The only requirement is that your code runs through some loop, which checks the CancellationPending every period of time (CheckPerMilliseconds).

private void ResetBackgroundWorker()
{
    backgroundWorker.CancelAsync();

    Task taskStart = Task.Run(() => 
    {
        Thread.Sleep(CheckPerMilliseconds);
        backgroundWorker.RunWorkerAsync();
    });
}

Inside the backgroundworker I use a for-loop that checks the CancellationPending.

private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;

    while(true)
    {
        if (backgroundWorker.CancellationPending)
        {
            return;
        }

        //Do something you want to do periodically.

        for (int i = 0; i < minutesToDoTask * 60; i++)
        {
            if (backgroundWorker.CancellationPending)
            {
                return;
            }

            Thread.Sleep(CheckPerMilliseconds);
        }
    }
}

Upvotes: 0

Jake Brewer
Jake Brewer

Reputation: 2634

I want to leave my requests running, but no longer care about the results. I override the value of the background worker (my busy spinner is using the isBusy flag).

    private void SearchWorkerCreate() {
        this.searchWorker = new BackgroundWorker();
        this.searchWorker.DoWork += this.SearchWorkerWork;
        this.searchWorker.RunWorkerCompleted += this.SearchWorkerFinish;
    }

    private void SearchWorkerStart(string criteria){
        if(this.searchWorker.IsBusy){
            this.SearchWorkerCreate();
        }
        this.searchWorker.RunWorkerAsync(criteria);
        this.OnPropertyChanged(() => this.IsBusy);
        this.OnPropertyChanged(() => this.IsIdle);
    }

Upvotes: 0

Pondidum
Pondidum

Reputation: 11617

The backgriound work itself does not do any cancleing.

When you call bgw.CancelAsync it sets a flag on the background worker that you need to check yourself in the DoWork handler.

something like:

bool _restart = false;

private void button1_Click(object sender, EventArgs e)
{
    bgw.CancelAsync();
    _restart = true;
}

private void bgw_DoWork(object sender, DoWorkEventArgs e)
{

    for (int i = 0; i < 300; i++)
    {
        if (bgw.CancellationPending)
        {
            break;
        }
        //time consuming calculation
    }
}

private void bgw_WorkComplete(object sender, eventargs e)  //no ide to hand not sure on name/args
{
    if (_restart)
    {
        bgw.RunWorkerAsync();
        _restart = false;
    }

}

Upvotes: 11

Eric Smith
Eric Smith

Reputation: 5392

There are a couple of options, it all depends on how you want to skin this cat:

If you want to continue to use BackgroundWorker, then you need to respect the model that has been established, that is, one of "progress sensitivity". The stuff inside DoWork is clearly required to always be aware of whether or not the a pending cancellation is due (i.e., there needs to be a certain amount of polling taking place in your DoWork loop).

If your calculation code is monolithic and you don't want to mess with it, then don't use BackgroundWorker, but rather fire up your own thread--this way you can forcefully kill it if needs be.

Upvotes: 2

TheVillageIdiot
TheVillageIdiot

Reputation: 40497

You can hook the change event handler for the controls in which the values are changed and do the following in the handler:

if(!bgWrkr.IsBusy)
     //start worker
else if(!bgWrkr.CancellationPending)
  bgWrkr.CancelAsync();

Hope it helps you!

Upvotes: 0

Related Questions