Hi all,

I am currently working on a "game of life" program. Which basically updates a grid and forms interesting patterns.

Now part of the program means it has to have a "start" and "stop" button. The idea being that the user can click one button to start the game of life animating, and the next button to stop the animation.

Now obviously to allow the user to have control over the GUI elements, I have incorporated a background thread to allow this. However I have problems when I run the program :(

Some background:

The "grid" is basically a stretched bitmap with the pixels acting as cells. The game of life checks how many pixels around it are occupied, and then works out if the cell should be "Alive" or "Dead" in the next iteration.

i.e. if pixel if populated and has 3 neighbors it lives. Draw it on the next bitmap. Swap the old bitmap with the new one and Refresh to show the next iteration.

Now this works fine when I don't use a background thread, and just go through the iterations step-by-step.

The problem is now that I have used this background thread, and click start, the animation works fine. Up until I move my mouse of off the button. When I move my mouse from the button it throws "InvalidOperationException was unhandled by user code - Object is currently in use elsewhere" I'm pretty sure this is because my mouse is moving and causing the form to animate in some way.

Does anyone have any ideas/suggestions on how to fix this? I've spent a few days and think I've hit a brick wall with this. Code beneath.

//Throws the error on one of the lines testing the neighboring cell. Like this one:

testn = CurrentBitmap.GetPixel(x - 1, y);

//incorporation of background worker

if (loopbreak == null)
            {
                start = true;
                loopbreak = new BackgroundWorker();
                loopbreak.DoWork += new DoWorkEventHandler(loopbreak_commence);
                loopbreak.RunWorkerAsync();

            }

//Apply the rules on click

 private void loopbreak_commence(object sender, DoWorkEventArgs e)
        {
            while (start == true)
            {
                if (!start)
                {
                    start = false;
                    break;
                }

                applyrules();
                SwapImages();



                //invoke the refresh
                Invoke(new MyDelegate(refr), true);
           }
}     

//invoke refresh - This isn't the problem. Error still occurs when this is commented out

 delegate void MyDelegate(bool refr);

        public void refr(bool refr)
        {
            Refresh();
        }

Recommended Answers

All 8 Replies

It's probably the bitmap object that is causing the issue, it being used by the GUI and whatever code you use to update the bitmap.

OK, I will have a play with that... How would one go about changing this? Should I define a new bitmap?

There is quite some methods missing to point out what has to be locked. But you probably can find out. What you have to do is to prevent more than one thread (in this case backgroundworker and main thread) to access the same data. This ain't threadsafe, because two threads are trying to access an object at the same time.

To prevent this, you need to use the lock keyword.

private static object _lock = new object();
//then lock the part of code that is causing the error.
lock(_lock){
//your code
}

What this does is, that it prevents multiple thread to access the locked content. The thread will remain in waiting mode until the _lock object is released (when its get out of the scope of the lock() { }). Note that if multi threading, the threads will queue up.

Hope this helps :)

Thanks for the feedback.

I have tried locking and sadly it doesn't seem to work :( The problem is when the backgroundworker calls the "applyrules()" method. Which amends the bitmap. I'm not sure of another way to implement "Stop" and "Start" buttons to this. Does anyone else have any ideas?

Code on the rules beneath:

private void applyrules()
        {
           


            for (int y = 0; y < rows; y++)
            {
                for (int x = 0; x < cols; x++)
                    {

                    int n = 0;

                    testpixel = CurrentBitmap.GetPixel(x, y);

                    if (x > 0)
                    {
                        if (y > 0)
                        {
                            //1st test of 8
                            testn = CurrentBitmap.GetPixel(x - 1, y - 1);
                            if (testn == Color.FromArgb(0, 0, 0))
                            {
                                n = n + 1;
                            }
                        }
//Tests 2 - 8

Stack trace:

at System.Drawing.Image.get_Height()
at System.Drawing.Bitmap.GetPixel(Int32 x, Int32 y)
at WindowsFormsApplication1.Form1.applyrules()

Try locking every place where the bitmap object is used. If this bitmap is the only problem, it should solve it.

Managed to solve the problem after hours and hours... Posting on here and the feedback I got helped me to think outside of the box so thanks guys :)

I had to invoke it. THAT simple. This is the thing I love and hate about programming... It can take hours to solve something simple, but the rush you get from fixing it is better than anything else in the world!

Again, thanks to everyone who responded. Greatly appreciated.

Ahh your right, the error you get when a lock is required is. "Illegal cross-threaded operation"

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.