Итак, я сделал приложение, которое использует несколько потоков и имитирует гонку между 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) везде, он все равно исключает исключения. Исключение всегда происходит, если кнопки перемещаются, когда я закрываю форму.
Спасибо за любую помощь!
(Я читал вопросы об этом исключении. Не помогло. Мне нужны ответы, а не ссылки, спасибо.)