0

On every click on pictureBox, I add object in list which is type Car. I want to make them move as soon as i click on picutreBox.

Here is my code

private Thread t;
private void pictureBox1_MouseClick_1(object sender, MouseEventArgs e)
{                
    list.Add(new Car(e.X, e.Y, 40, 40));
    br++;
    t = new Thread(Draw);
    t.Start();  
}

Draw:

private void Draw()
{
    Graphics g = pictureBox1.CreateGraphics();           
    for(int i = 0; i < 1000; i++)
    {
        list[br].DrawCar(g, Color.Red);
        list[br].Move();               
        Thread.Sleep(100);
        pictureBox1.Invoke(
            (MethodInvoker)delegate
            {
                pictureBox1.Refresh();
            });
    }            
    g.Dispose();
}

The problems i have are following:

  1. When i click first time, it is moving nicely, but as soon as i click again , car stops and next car starts with moving.

  2. The more i click on form, the car is moving faster, i dont know why

  3. When i exit from form, i get an Exception:

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

AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
  • 1
    Anything involving the display can only happen in the UI thread (which is why you need Invoke). So, why would you use a thread?? Also: Anything you draw with `Graphics g = pictureBox1.CreateGraphics();` will not persist. More mistakes may be in the `Move` code, but we can't see it. – TaW May 24 '18 at 17:02
  • Little formatting type, `
    ` doesn't do anything on this site. If you want a new line, you have to use enter twice in a row.
    – AustinWBryan Jul 03 '18 at 03:08
  • There is a small insanity calling `new Thread(...)` each time. Creating a thread is computationally expensive, takes over 1MB of RAM, and is slow. The advantage is only there if you are about to execute a CPU intensive operation. That doesn't appear to be the case for your code. – Enigmativity Jul 03 '18 at 03:27

2 Answers2

1
  1. The first car stops because br is incremented and the Draw function now moves the second car in the list.
  2. If you click the picture box multiple times there will be multiple threads running the Draw function and they are all moving the same car (see 1.)
  3. When the form closes and a thread is still running, the thread tries to access the picture box. It might not exist anymore.

Solutions

  1. Make br a local variable and pass br as a parameter to the thread.Start() method.
  2. Should be fixed by 1.
  3. In the OnClosing of the form stop all the threads
Emond
  • 50,210
  • 11
  • 84
  • 115
1

I see several red flags in your code.

Creating a new thread each time. What happens to the old thread? Also creating a new thread to move each car isn't ideal.

Using br to index which Car in the list to move and draw. When you add the second car, br is now 1 so now the first Draw thread will use list[1]. Now you have 2 threads both moving the 2nd car. This is why the first car stops moving and the 2nd car starts moving faster.

Invoking pictureBox refresh isn't ideal either.

I would do it more like this:

List<System.Windows.Forms.Timer> timers =
  new List<System.Windows.Forms.Timer>();
List<Car> list = new List<Car>();

private void button1_Click(object sender, EventArgs e)
{
  Car car = new Car(50, 50, 40, 40);
  list.Add(car);
  Timer timer = new Timer();
  timer.Tick += Timer_Tick;
  timer.Interval = 100;
  timer.Tag = car;
  timer.Start();
  timers.Add(timer);
}

private void Timer_Tick(object sender, EventArgs e)
{
  Car car = (Car)((sender as Timer).Tag);
  car.Move();
  pictureBox1.Invalidate();
}

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
  Graphics g = e.Graphics;
  g.Clear(Color.White);

  foreach (Car car in list.ToArray())
  {
    car.DrawCar(g, Color.Blue);
  }
}

There may be other issues in car.Move and DrawCar.

gunnerone
  • 3,566
  • 2
  • 14
  • 18
  • This is dangerous because the list is potentially getting modified while iterating over it. A lock should be used to protect the collection from this. – Emond May 25 '18 at 14:27