3

I am working with Background Worker but neither i am able to synchronize my progress bar nor able to stop or abort the process.

in my dowork function

void bw_DoWork(object sender, DoWorkEventArgs e)
{
    if(bw.CancellationPending==true)
    {
        e.cancel=true;
        return;
    }
    else
    {
        e.Result = abc();
    }
}
int abc()
{
    //my work
    Count++;
    return count;
}

void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if(bw.CancellationPending==true)
    {
        button17.Visibility = Visibility.Visible;
        label1.Content = "Aborted";
    }
    button17.Visibility = Visibility.Visible;
    label1.Content = "Completed";
}
private void Cancel_Click(object sender, RoutedEventArgs e)
{
    if(bw.IsBusy)
    {
        bw.CancelAsync();
    }
}

Now i want to know how could i Synchronize my Progress Bar and how to exit from the process?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Neel Bhasin
  • 749
  • 1
  • 7
  • 22

3 Answers3

1

Have you set the BackgroundWorker.WorkerReportsProgress && BackgroundWorker.WorkerSupportsCancellation properties on your instance to be true?

e.g.

var myBackgroundWorker = new BackgroundWorker();
myBackgroundWorker.WorkerReportsProgress = true;
myBackgroundWorker.WorkerSupportsCancellation = true;
//the rest of the init

If you want to report progress, you need to call the BackgroundWorker.ReportProgress() method from inside your DoWork.

Alastair Pitts
  • 19,423
  • 9
  • 68
  • 97
  • i am using the same properties but still it is not able to abort the process. and for `BackgroundWorker.ReportProgress()` what parameters do i need to pass? – Neel Bhasin Aug 01 '13 at 07:22
  • @neelb2 I linked to the MSDN page for that method and you have access to the intellisense. I think you can work out what the parameters are. – Alastair Pitts Aug 02 '13 at 00:08
0

This is a rubbish and trivial answer but give the Task Parallel library a whirl. http://msdn.microsoft.com/en-us/library/dd537608.aspx

This library encapsulates threads as discrete Task objects. It supports cancellation.

Be warned that in a worker thread, pause and cancellation operation have to be supported by the worker code itself, by polling pause/cancel flags and tokens. You cannot safely achieve these operations with threads alone.

It is a nicer pattern to work with

As for your question, 2 flags are required to support your operations. You will be need to check them at intervals during the worker code.

bool pause = false;
bool cancel = false;
void DoWork()
{
    try
    {
        ...
        //periodically check the flags
        if(cancel) return;
        while(paused){}; //spin on pause
        ...
    }
    finally
    {
        //cleanup operation
    }
}

Alastair Pitts' answer illustrates how background worker supports these features. So does MSDN ;) http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx

Gusdor
  • 14,001
  • 2
  • 52
  • 64
  • I have gone through this link it is also not helping me in correct manner. do you have any Straight forward solution? – Neel Bhasin Aug 01 '13 at 07:25
  • I'll be honest, the other answers are better but for completeness I wanted to give you information about the Task pattern as it is more flexible than the Async Event Pattern that background worker implements. I also wanted to highlight for you the actual process that you should be taking to implement cancellation and pausing as removed from the background worker - I found the event focus confusing when i was learning it. – Gusdor Aug 01 '13 at 07:41
0

(You might want to check out this other SO question/answer for details about the new async facility! It greatly improves the quality of life of developing this kind of operations!)

BackgroundWorker is event-based, basic usage is the following (the link provides many useful additional details):

var worker = new BackgroundWorker();

// The following two props must be true:
// #1: The worker will be enabled to signal its progress
worker.WorkerReportsProgress = true;
// #2: The worker will accept cancellation
worker.WorkerSupportsCancellation = true;

// Now the events:

worker.DoWork += (s,e) => 
{         
    int i = 0; // This goes from 0 to 100
    // Do code, update 'i'
    worker.ReportProgress(i); 

    worker.CancelAsync();     //... to cancel the worker if needed

    // WARNING: This code *cannot* interact with the UI because
    // it's running in a different thread
};

worker.ProgressChanged += (s,e)=> 
{ 
// This is executed when you call ReportProgress() from DoWork() handler
// IMPORTANT: All UI interaction **must** happen here    

// e.ProgressPercentage gives you the value of the parameter you passed to
// ReportProgress() (this mechanism is a perfect fit for a progress bar!)
};

worker.RunWorkerCompleted+= (s,e) => 
{
    // code here runs when DoWork() is done, is canceled or throws.
    // To check what happened, the link provides this sample code:
    if (e.Cancelled == true)
    {
        // Cancelled!
    }
    else if (e.Error != null)
    {
        // Exception !
    }
    else
    {
        // Work completed!
    }
};

worker.RunWorkerAsync();

It's important to know that (extracted from the link above):

You must be careful not to manipulate any user-interface objects in your DoWork event handler. Instead, communicate to the user interface through the ProgressChanged and RunWorkerCompleted events.

UPDATE Lambdas here are used to keep code compact. You can obviously use "normal" handlers or whatever other method of attaching code to events you like/want/need.

Community
  • 1
  • 1
Alex
  • 23,004
  • 4
  • 39
  • 73
  • Using lambda expressions as event handlers is very poor practice - anonymous delegates cannot be removed from the invocation list. Could you update your answer to explain why it is OK in this scenario? Otherwise, the answer is great. – Gusdor Aug 01 '13 at 07:19