System.ObjectDisposedException при многопоточности? - PullRequest
0 голосов
/ 15 апреля 2020

Итак, я сделал приложение, которое использует несколько потоков и имитирует гонку между 3 байкерами.

В моей форме у меня есть 3 кнопки, что такое байкеры, 3 панели (первая стартовая линия, вторая депо панель, третья финиш sh). Байкеры начинаются с левой стороны окна, но не на стартовой панели. Если я нажму кнопку пуска, они начнут с go до панели запуска. Под стартовой панелью и панелью депо у меня есть кнопка 1-1. Если я нажму кнопку под стартовой панелью, все 3 байкера начнут с go в направлении панели депо, где они останавливаются. Каждый раз, когда я нажимаю кнопку под панелью депо, он позволяет байкеру финишировать sh гонку и go к финишу sh.

Код:

// I start a thread for every button (biker)
private void bStart_Click(object sender, EventArgs e)
{
    startBike(bBike1);
    startBike(bBike2);
    startBike(bBike3);
}

private void startBike(Button bBike)
{
    Thread t = new Thread(BikeThreadFunction);
    bBike.Tag = t;
    t.IsBackground = true;
    t.Start(bBike);
}

private ManualResetEvent startPanelRun = new ManualResetEvent(false);
private AutoResetEvent depoPanelRun = new AutoResetEvent(false);
Random random = new Random();
bool closed = false;
delegate void BikeAction(Button bike);

protected override void OnClosed(EventArgs e)
    {
        base.OnClosed(e);
        closed = true;
    }
// The problem happens here in every "while (bike.Left <" row, if I put them between try-catch
// the program does not die but I see the exception happened
// I would like these lines (if I close the application) to not run or something to prevent this exception to happen
public void BikeThreadFunction(object param)
    {
        try
        {
            Button bike = (Button)param;
            bike.Tag = Thread.CurrentThread;

            while (bike.Left < startpanel.Left)
            {
                MoveBike(bike);
                Thread.Sleep(100);

            }

            if (startPanelRun.WaitOne())
            {
                while (bike.Left < depopanel.Left)
                {
                    MoveBike(bike);
                    Thread.Sleep(100);

                }
                if (depoPanelRun.WaitOne())
                    while (bike.Left < finishpanel.Left)
                    {
                        MoveBike(bike);
                        Thread.Sleep(100);
                    }
            }
        } catch (ThreadInterruptedException)
        {

        }

    }

// The exception also happens here in the "Invoke(new BikeAction(MoveBike), bike);" row
public void MoveBike(Button bike)
    {

        if (closed)
            return;
        if (InvokeRequired)
        {
            Invoke(new BikeAction(MoveBike), bike);
        }
        else
        {
            if (!IsDisposed)
            {
                int step = random.Next(3, 9);
                bike.Left += step;
            }
        }
    }

private void bStep1_Click(object sender, EventArgs e)
{
    startPanelRun.Set();
}
private void bStep2_Click(object sender, EventArgs e)
{
    depoPanelRun.Set();
}

Это исключение было первоначально сгенерировано в этом стеке вызовов: System. Windows .Forms.Control.MarshaledInvoke (System. Windows .Forms.Control, System.Delegate, object [], bool) System . Windows .Forms.Control.Invoke (System.Delegate, object []) System. Windows .Forms.Control.Invoke (System.Delegate, object []) racing_bikers.Form1.MoveBike (System. Windows .Forms.Button) в Form1.cs racing_bikers.Form1.MoveBike (System. Windows .Forms.Button) в Form1.cs racing_bikers.Form1.BikeThreadFunction (объект) в Form1.cs System.Threading.ThreadHelper.ThreadStart_Context (объект ) System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext, System.Threading.ContextCallback, object, bool) System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext, System.Threading.ContextCallback, объект, bool) .Threading.Executio nContext.Run (System.Threading.ExecutionContext, System.Threading.ContextCallback, object) ...

Я знаю, что это происходит, потому что он пытается что-то сделать с помощью элемента формы (кнопки байкера), который был закрыт, но даже если я поместил (! IsDisposed) или (! closed) везде, он все равно исключает исключения. Исключение всегда происходит, если кнопки перемещаются, когда я закрываю форму.

Спасибо за любую помощь!

(Я читал вопросы об этом исключении. Не помогло. Мне нужны ответы, а не ссылки, спасибо.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...