How to stop BackgroundWorker on Form's Closing event?

c# stop backgroundworker
winforms backgroundworker
uwp backgroundworker
c# backgroundworker set error
backgroundworker dowork
how to create a worker thread in c#
background worker thread c# in mvc
multithreading with backgroundworker in c#

I have a form that spawns a BackgroundWorker, that should update form's own textbox (on main thread), hence Invoke((Action) (...)); call. If in HandleClosingEvent I just do bgWorker.CancelAsync() then I get ObjectDisposedException on Invoke(...) call, understandably. But if I sit in HandleClosingEvent and wait for bgWorker to be done, than .Invoke(...) never returns, also understandably.

Any ideas how do I close this app without getting the exception, or the deadlock?

Following are 3 relevant methods of the simple Form1 class:

    public Form1() {
        InitializeComponent();
        Closing += HandleClosingEvent;
        this.bgWorker.RunWorkerAsync();
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {
        while (!this.bgWorker.CancellationPending) {
            Invoke((Action) (() => { this.textBox1.Text = Environment.TickCount.ToString(); }));
        }
    }

    private void HandleClosingEvent(object sender, CancelEventArgs e) {
        this.bgWorker.CancelAsync();
        /////// while (this.bgWorker.CancellationPending) {} // deadlock
    }

The only deadlock-safe and exception-safe way to do this that I know is to actually cancel the FormClosing event. Set e.Cancel = true if the BGW is still running and set a flag to indicate that the user requested a close. Then check that flag in the BGW's RunWorkerCompleted event handler and call Close() if it is set.

private bool closePending;

protected override void OnFormClosing(FormClosingEventArgs e) {
    if (backgroundWorker1.IsBusy) {
        closePending = true;
        backgroundWorker1.CancelAsync();
        e.Cancel = true;
        this.Enabled = false;   // or this.Hide()
        return;
    }
    base.OnFormClosing(e);
}

void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
    if (closePending) this.Close();
    closePending = false;
    // etc...
}

Cancelling the BackgroundWorker, Because if the UI thread is busy performing your lengthy task, no input will be processed, meaning that no matter how hard your user hits a Cancel button or the  CancelAsync submits a request to terminate the pending background operation and sets the CancellationPending property to true. When you call CancelAsync, your worker method has an opportunity to stop its execution and exit.

I've found another way. If you have more backgroundWorkers you can make:

List<Thread> bgWorkersThreads  = new List<Thread>();

and in every backgroundWorker's DoWork method make:

bgWorkesThreads.Add(Thread.CurrentThread);

Arter that you can use:

foreach (Thread thread in this.bgWorkersThreads) 
{
     thread.Abort();    
}

I used this in Word Add-in in Control, which i use in CustomTaskPane. If someone close the document or application earlier then all my backgroundWorkes finishes their work, it raises some COM Exception(I don't remember exatly which).CancelAsync() doesn't work.

But with this, I can close all threads which are used by backgroundworkers Immediately in DocumentBeforeClose event and my problem is solved.

How do I stop a BackgroundWorker thread?, Windows.Forms.MessageBox.Show("Loop stoped at " + i.ToString()) Once your busy function returned, background worker stops thread  In this Video, I am going to show you, How to use BackgroundWorker control in windows forms C#. How to do task in back ground.

Here was my solution (Sorry it's in VB.Net).

When I run the FormClosing event I run BackgroundWorker1.CancelAsync() to set the CancellationPending value to True. Unfortunately, the program never really gets a chance to check the value CancellationPending value to set e.Cancel to true (which as far as I can tell, can only be done in BackgroundWorker1_DoWork). I didn't remove that line, although it doesn't really seem to make a difference.

I added a line that would set my global variable, bClosingForm, to True. Then I added a line of code in my BackgroundWorker_WorkCompleted to check both e.Cancelled as well as the global variable, bClosingForm, before performing any ending steps.

Using this template, you should be able to close your form out at any time even if the backgroundworker is in the middle of something (which might not be good, but it's bound to happen so it might as well be dealt with). I'm not sure if it's necessary, but you could dispose the Background worker entirely in the Form_Closed event after this all takes place.

Private bClosingForm As Boolean = False

Private Sub SomeFormName_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    bClosingForm = True
    BackgroundWorker1.CancelAsync() 
End Sub

Private Sub backgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    'Run background tasks:
    If BackgroundWorker1.CancellationPending Then
        e.Cancel = True
    Else
        'Background work here
    End If
End Sub

Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    If Not bClosingForm Then
        If Not e.Cancelled Then
            'Completion Work here
        End If
    End If
End Sub

https://social.msdn.microsoft.com/Forums/vstudio/e, https://docs.microsoft.com › › Windows Forms › Windows Forms controls The BackgroundWorker does exactly as its title implies. It works in the background in a separate thread. This is great if you have some complex calculation or maybe you're connecting to a slow server from your application and it blocks the UI thread.

Can you not wait on the signal in the destructor of the form?

AutoResetEvent workerDone = new AutoResetEvent();

private void HandleClosingEvent(object sender, CancelEventArgs e)
{
    this.bgWorker.CancelAsync();
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    while (!this.bgWorker.CancellationPending) {
        Invoke((Action) (() => { this.textBox1.Text =   
                                 Environment.TickCount.ToString(); }));
    }
}


private ~Form1()
{
    workerDone.WaitOne();
}


void backgroundWorker1_RunWorkerCompleted( Object sender, RunWorkerCompletedEventArgs e )
{
    workerDone.Set();
}

Walkthrough: Implementing a Form That Uses a Background , Creating a BackgroundWorker in Your Form the second Button control cancelAsyncButton , and set the Text property to Cancel Async . We need to create a form with a textbox, a button, a progress bar and a label. This isn’t essential to the BackgroundWorker, but it will help create our example program. If you aren’t familiar with WPF or XAML, XAML is the markup language used to create interfaces in WPF, much like HTML to web development.

Firstly, the ObjectDisposedException is only one possible pitfall here. Running the OP's code has produced the following InvalidOperationException on a substantial number of occasions:

Invoke or BeginInvoke cannot be called on a control until the window handle has been created.

I suppose this could be amended by starting the worker on the 'Loaded' callback rather than the constructor, but this entire ordeal can be avoided altogether if BackgroundWorker's Progress reporting mechanism is used. The following works well:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    while (!this.bgWorker.CancellationPending)
    {
        this.bgWorker.ReportProgress(Environment.TickCount);
        Thread.Sleep(1);
    }
}

private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    this.textBox1.Text = e.ProgressPercentage.ToString();
}

I kind of hijacked the percentage parameter but one can use the other overload to pass any parameter.

It is interesting to note that removing the above sleep call clogs the UI, consumes high CPU and continually increases the memory use. I guess it has something to do with the message queue of the GUI being overloaded. However, with the sleep call intact, the CPU usage is virtually 0 and the memory usage seems fine, too. To be prudent, perhaps a higher value than 1 ms should be used? An expert opinion here would be appreciated... Update: It appears that as long as the update isn't too frequent, it should be OK: Link

In any case, I can't foresee a scenario where the updating of the GUI has to be in intervals shorter than a couple of milliseconds (at least, in scenarios where a human is watching the GUI), so I think most of the time progress reporting would be the right choice

BackgroundWorker In C#, C# BackgroundWorker component executes code in a separate dedicated by dragging onto a Form or at run-time using the BackgroundWorker class. Start button click starts the processing BackgroundWorker and Stop  To try this code, create a Windows Forms application. Add a Label control named resultLabel and add two Button controls named startAsyncButton and cancelAsyncButton. Create Click event handlers for both buttons. From the Components tab of the Toolbox, add a BackgroundWorker component named backgroundWorker1.

[RESOLVED] How can I make a BackGroundWorker finish/complete , I have a form which asks the user for input and then turns this into a to stop the background worker from running whilst this code is executed. Start button click starts the processing BackgroundWorker and Stop button click stops the processing. While BackgroundWorker is doing work in the background, you may still type anything in the RichTextBox control. The Start and Stop button click event handlers look like this.

MultithreadFact on Twitter: "How to stop BackgroundWorker on , How to stop BackgroundWorker on Form's Closing event? - http://bit.ly/1cbx1vY. 5​:00 PM - 25 Feb 2016. 0 replies 0 retweets 0 likes. Reply. Retweet. Retweeted. The next video is starting stop. Loading Watch Queue Queue. __count__/__total__ Find out why Close. How to use the background worker - C# Tutorial BackgroundWorker in windows forms

How to stop Backgroundworker and close the form? - .net - iOS, I want to completely stop the BackgroundWorker DoWork() Process while running for closing the form. I have applied following code but in "this.Invoke" it throws 

Comments
  • Have you tried to use BegingInvoke instead of Invoke so you don't have to wait until the invokemessage returns?
  • Yes. No dead lock, but I don't know when BeginInvoke has been processed (on the main thread), so I'm back to ObjectDisposed exception.
  • This works. I used workersThread.CancellationPending + workersThread.IsBusy flags, instead of mCompleted.
  • That's kinda dangerous, IsBusy is a property of an asynchronous thread. It could race. It actually doesn't, but that was luck. Also, CancellationPending is reset before RunWorkerCompleted fires.
  • Minor piece of information: you need to tell your BackGroundWorker instance that it can be cancelled.
  • Speaking of races... Wouldn't this fail to close, if the worker happens to complete normally right after if (!mCompleted)?
  • @lain : No, OnFormClosing and backgroundWorker1_RunWorkerCompleted both run on the UI thread. One cannot be interrupted by the other.
  • +1 Handle this at the BackgroundWorker's RunWorkerCompleted EventHandler. That's what I do
  • WindowsFormsSynchronizationContext.Post(...) just calls BeginInvoke(...), so it isn't much different from Invoke() I'm doing already. Unless I miss something, could you please elaborate?
  • this sounds very hacky to me. won't do this.