0

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.

Helem Shoshi
  • 239
  • 1
  • 3
  • 14
  • 2
    You must do "Cooperative cancellation" in your do work function. In other words its your responsibility to check if `bgw.CancellationPending == true` in your DoWork code and act appropriately. – Scott Chamberlain Feb 05 '15 at 05:35
  • Maybe the problem is not the backgroundworker it self but the loop in the DoWork that is very long so maybe i need somehow to stop the loop when closing the form ? – Helem Shoshi Feb 05 '15 at 05:36
  • 1
    Beside Scott's answer + comment, solution to your thrown error would be to use checks for IsDisposed() and IsDisposing() – Kavindu Dodanduwa Feb 05 '15 at 05:48
  • Edited my question with what i tried now still getting the exception when closing the form. The backgroundworker operation never cancelled. It's giving me the same exception all the time cant access disposed object. – Helem Shoshi Feb 05 '15 at 08:15
  • See [How to stop BackgroundWorker on Form's Closing event?](http://stackoverflow.com/a/1732361/719186). That being said, you are doing an awful lot of UI work in that background thread, rendering it rather in-effective as a background worker. – LarsTech Feb 05 '15 at 08:34

2 Answers2

2

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) 
     {
       //...
     }
}
Pankaj
  • 2,618
  • 3
  • 25
  • 47
1

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)

Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
  • Actually - depending on how tight your loops are and how many iterations you have - you may want to place it in two spots. Once at the beginning of the method, then in the outer for loop. Generally - you would want to check for cancellation before any major operation or iteration of an operation. If you are doing a million iterations - this isn't feasible, but if you are doing thousands and they are intensive - it would make sense here. – tsells Feb 05 '15 at 06:04
  • tsells in the loop i have now about 5000 files(images). – Helem Shoshi Feb 05 '15 at 08:15