Заставить объекты двигаться с помощью потоков - PullRequest
0 голосов
/ 24 мая 2018

При каждом нажатии на pictureBox я добавляю в список объект типа Car.Я хочу заставить их двигаться, как только я нажму picutreBox.

Вот мой код

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();  
}

Ничья:

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();
}

У меня проблемыследующие:

  1. Когда я нажимаю в первый раз, он движется хорошо, но как только я нажимаю снова, машина останавливается, и следующая машина начинает движение.

  2. Чем больше я нажимаю на форму, тем быстрее движется машина, я не знаю, почему

  3. Когда я выхожу из формы, я получаю исключение:

System.InvalidOperationException: 'Invoke или BeginInvoke не могут быть вызваны для элемента управления, пока не создан дескриптор окна.'

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

Я вижу несколько красных флажков в вашем коде.

Создание нового потока каждый раз.Что происходит со старым потоком?Кроме того, создание новой темы для перемещения каждого автомобиля не является идеальным.

Использование br для указания того, какой автомобиль в списке следует перемещать и рисовать.Когда вы добавляете вторую машину, br теперь равно 1, поэтому теперь первая ветка Draw будет использовать list [1].Теперь у вас есть 2 потока, которые двигают 2-ю машину.Вот почему первая машина перестает двигаться, а вторая начинает двигаться быстрее.

Вызов обновления изображения Boxbox тоже не идеален.

Я бы сделал это больше так:

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);
  }
}

Возможны другие проблемы с автомобилем. Перемещение и DrawCar.

0 голосов
/ 24 мая 2018
  1. Первая машина останавливается, так как br увеличивается, а функция Draw теперь перемещает вторую машину в списке.
  2. Если вы щелкнете мышью по окну с изображением несколько раз, будет несколько потоков, выполняющих функцию Drawи все они движутся на одной машине (см. 1).
  3. Когда форма закрывается и поток все еще работает, поток пытается получить доступ к графическому блоку.Возможно, он больше не существует.

Решения

  1. Сделайте br локальной переменной и передайте br в качестве параметра методу thread.Start ().
  2. Должно быть зафиксировано 1.
  3. В закрытии формы остановите все потоки
...