简体   繁体   中英

C# - How to work with background worker with custom code -Run,Pause,Stop?

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?

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

eg

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 .

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

(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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM