Helem Shoshi
Helem Shoshi

Reputation: 239

How do i cancel backgroundworker operation in the middle when closing the form?

I have this DoWork event code:

private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker bgw = (BackgroundWorker)sender;
            if (bgw.CancellationPending == true)
            {
                return;
            }
            else
            {
            Bitmap newbmp = new Bitmap(512, 512);
            IEnumerable<Point> CommonList = null;
            StreamWriter w = new StreamWriter(@"c:\diff\diff.txt");
            pixelscoordinatesinrectangle = new List<Point>();
            pixelscoordinatesinrectangle = pointsAffected.ToList();
            DrawIt = false;
            for (int i = 0; i < trackBar1FileInfo.Length; i++)
            {
                DrawIt = true;
                trackBar1.Invoke(new MethodInvoker(delegate { trackBar1.Value = i; }));


                        timer1.Stop();
                        Button1Code();
                        timer1.Start();
                        trackBar2.Invoke(new MethodInvoker(delegate { trackBar2.Enabled = false; }));
                        trackBar1.Invoke(new MethodInvoker(delegate { trackBar1.Enabled = false; }));
                        trackBar1.Invoke(new MethodInvoker(delegate { LoadPictureAt(trackBar1.Value, sender); }));
                        pictureBox1.Load(trackBar1FileInfo[i].FullName);
                        trackBar1.Invoke(new MethodInvoker(delegate {
                            ConvertedBmp = ConvertTo24(trackBar1FileInfo[trackBar1.Value].FullName);
                        }));

                    ConvertedBmp.Save(ConvertedBmpDir + "\\ConvertedBmp.bmp");
                    mymem = ToStream(ConvertedBmp, ImageFormat.Bmp);
                    Button1Code();

                    pictureBox1.Invoke(new MethodInvoker(delegate { pictureBox1.Refresh(); }));                    
                    newpixelscoordinates = new List<Point>();
                    newpixelscoordinates = pointsAffected.ToList();
                    CommonList = pixelscoordinatesinrectangle.Intersect(newpixelscoordinates);
                    foreach (Point s in CommonList)
                    {
                        w.WriteLine("The following points are the same" + s);
                        newbmp.SetPixel(s.X, s.Y, Color.Red);
                    }
                }
                w.Close();
                using (Graphics G = Graphics.FromImage(newbmp))
                newbmp.Save(@"c:\newbmp\newbmp.bmp", ImageFormat.Bmp);
                newbmp.Dispose();
            }
        }

The problem is when the backgroundworker dowork is working doing the job and then i close the form in the middle. Then it throw each time on a different line in the DoWork event exception say:

Cannot access a disposed object

For example on this line:

trackBar1.Invoke(new MethodInvoker(delegate { trackBar1.Value = i; }));

I tried in the FormClosing event to do:

backgroundWorker2.CancelAsync();

But it didn't do anything.

And i set in the designer backgroundworker2 WorkerSupportsCancellation to true already.

Inside the loop i tried for example to do that:

pictureBox1.Invoke(new MethodInvoker(delegate { pictureBox1.Refresh();
                    if (bgw.CancellationPending == true)
                    {
                        MessageBox.Show("cancelled");
                    }

                    }));

But nothing still i'm getting exception on this say: Cannot access a disposed object

Tried to add this bgw.CancellationPending check before the loop and in the top of the loop inside it. And inside every place in the loop i'm using the Begin Invoke

But still getting this exception all the time on a different line inside the loop.

In the form closing event i did:

private void ScanClouds_FormClosing(object sender, FormClosingEventArgs e)
        {

            backgroundWorker2.WorkerSupportsCancellation = true;
            backgroundWorker2.CancelAsync();
        }

And still when closing the form i'm getting the exception.

Upvotes: 0

Views: 349

Answers (2)

Pankaj
Pankaj

Reputation: 2744

Note that setting this flag

bgw.CancellationPending = true 

only notifies the worker thread that a cancel has been requested. The cancel will not actually happen until the thread in the DoWork checks this bgw.CancellationPending flag.

So you need to check in your loop

for (int i = 0; i < trackBar1FileInfo.Length; i++)
{
    if(bgw.CancellationPending == false) 
     {
       //...
     }
}

Upvotes: 2

Scott Chamberlain
Scott Chamberlain

Reputation: 127563

You only check if bgw.CancellationPending == true once in your DoWork code. You need to check that Every Single Time you come back from some operation that can "take a while", after each of your Invoke calls for example (it might be a good idea to try to combine some of them into a single Invoke and do more than one thing inside each call)

Upvotes: 1

Related Questions