Click here to Skip to main content
15,885,767 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I run the code below and only the last square in the list gets animated. I want all the squares animated, how?

What I have tried:

private void animateSquaresAfterConvertin(List<Point> lstOfConvertedNowPoints)
        {
            foreach (Point p in lstOfConvertedNowPoints)
            {
                animateThisSquarePoint(p);
            }
        }

        private void animateThisSquarePoint(Point p)
        {
            BackgroundWorker bgw = new BackgroundWorker();
            lstBackgroundWorkersAnimate.Add(bgw);
            bgw.DoWork += Bgw_DoWork;
            bgw.RunWorkerCompleted += Bgw_RunWorkerCompleted;
            bgw.RunWorkerAsync(p);
        }

        List<BackgroundWorker> lstBackgroundWorkersAnimate = new List<BackgroundWorker>();

        private void Bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            lstBackgroundWorkersAnimate.Remove(sender as BackgroundWorker);
            (sender as BackgroundWorker).Dispose();
        }



        Pen penForBGWAnimate = new Pen(Color.Purple);
        private void Bgw_DoWork(object sender, DoWorkEventArgs e)
        {
            Point p1 =(Point) e.Argument;

            g.DrawRectangle(penForBGWAnimate, p.X + S.Width * p1.X, p.Y + S.Height * p1.Y, S.Width, S.Height);

            System.Threading.Thread.Sleep(300);

            drawSquare(p1.X, p1.Y);
            Debug.WriteLine(p1.X.ToString()+p1.Y.ToString());
        }
Posted
Updated 23-May-21 16:25pm
v4

1 solution

You're already doing it, but you're doing drawing all wrong.

If you're drawing on a control, you can NOT do it from a background thread. Your "g" is defined elsewhere so it's impossible to say.

If you're going to draw on something, draw on a Bitmap. You do not need a bunch of BackgroundWorkers to do this. You just go through in a loop and draw on your Bitmap, then when the drawing is done, you can draw the entire Bitmap onto whatever control surface you're using.

Also, DO NOT CREATE GDI OBJECTS IN A LOOP, like your Pen! You're are creating GDI object but never Disposing it, so you're wasting system resources and will eventually crash your app and possibly Windows. Create your Pen once, possibly at the class level, and you can reuse it over and over again without creating new ones.

You don't need any BackgroundWorkers.
 
Share this answer
 
v2
Comments
George Swan 22-May-21 4:33am    
Dave is correct in what he says. There is another problem with your code, it seems to me that your Bgw_DoWork method is used by multiple threads all trying to share the same resources at the same time. This results in chaos. The only reason that the last worker in the list succeeds is that there is not a subsequent worker to interfere with it. Asynchronous coding is problematical -it is best avoided if possible.
john1990_1 22-May-21 6:09am    
I'm sorry, you got the code wrong, I'm running a: System.Threading.Thread.Sleep(300); and it would freeze my program and my program's window woldn't be able to move if it's not another task, I wouldn't have used BackGroundWorkers if I didn't need them, I will make the use of "Pen pen" for all in the same instance, would there be a problem of accessing "g" at the same time if the program is used for a long time? How to make many simultaneous async threads that animate the squares on board without having the window freeze for 300 ms?
Dave Kreskowiak 22-May-21 10:46am    
You don't use multiple threads. You build a "game loop" using a timer. On every tick, you update your data, use that data to draw on a Bitmap, then invalidate the control you're going to draw on. In the drawing code for that control, you just paint the Bitmap onto the control surface.
john1990_1 22-May-21 10:52am    
This works, I'm anyway interested in knowing if it's possible to make many BackGroundWorkers in a for loop as this would change my life... the way you described is a little resource inefficient and not very professional code, with RunWorkerComplete I can do some stuff and timers are going to be very problematic as RunWorkerComplete doesn't exist in timers, I want to change my C# life with learnig threads, how to make each thread stand by itself and not have only the last one alive?
Dave Kreskowiak 22-May-21 13:48pm    
:LAUGH: OK.

You're already creating a BackgroundWorker. All you have to do is wrap that code in a for loop to create as many as you want.

Keep in mind, your CPU only has so many cores, so creating more BackgroundWorkers than that is just creating jobs that will sit and wait for a CPU core to become available. So, if you create 100 BackgroundWorkers, only, say, 4 to 8 of them are going to run are any one time.

But, Graphics objects are NOT THREAD SAFE. That means only one thread can use it at a time.

Oh, you think you're going to create a new Graphics object per-thread? Think again. You can only have a single Graphics object open on a bitmap or other control surface at a time.

These limitation are imposed by GDI+.

You were saying something about "resource inefficient" and "not very professional code"? I'm sorry to tell you that's how game engines really work in the real world. You might want to go Google for "game loop" and start reading.

You can do all kinds of other work, gathering and updating data, in threads all you want. All the drawing has to be done in a single thread.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900