Я строю шахматную игру, и у меня есть цикл, который проходит через массив объектов и рисует изображения шахматных фигур на формах вин (каждая графическая рамка представляет часть).
public void PrintPieces(Pieces [,] pieces)
{
for (int i = 1; i < 9; i++)
{
for (int j = 1; j < 9; j++)
{ //pieces is an array of chess piece objects (pawn, king, bishop king etc)
if (pieces[i, j] is Object )
{
try
{
//The path of the image is obtained.
chessPics[i, j].Load(pieces[i, j].print());
}
catch (InvalidOperationException ex)
{
MessageBox.Show(ex.StackTrace);
}
}
else
{ //chesspics is an array of pictureboxes
chessPics[i, j].Image = null;
}
}
}
}
Вышеуказанный метод работает !!!
У меня есть больше кода игры .. но здесь это неактуально ,,
Я также добавил функцию воспроизведения, в которой участвует фоновый работник.
public void ReplayGame()
{
backgroundWorker1.WorkerSupportsCancellation = true;
backgroundWorker1.RunWorkerAsync();
}
Функция запускается при каждом нажатии кнопки «воспроизведения».
В этом методе выше, где я получаю условие гонки и два потока сталкиваются друг с другом .. (войти в цикл одновременно).
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//replay is an array of the chess moves that were made since
the start of the game.
foreach (KeyValuePair<int, int[]> item in replay)// count should be more than 2
{
if (!backgroundWorker1.CancellationPending)
{
//There is more code here that wasnt presented
//It basically executes each move from the replay
//array and return the chess pieces array (the positions
//of the current game after each move from teh replay array
//was executed)..The current game state returns in a form
//of an array and returns from the method:
PrintPieces(codeFile.PieceState());
}
else
{
break;
}
System.Threading.Thread.Sleep(1000);
}
//After the loop ends i am trying to cancel the operation of the background //worker...but that seems useless.
backgroundWorker1.CancelAsync();
}
Что действительно происходит в игре, так это:
Я нажимаю кнопку воспроизведения один раз .. Воспроизведение всех шахматных ходов выполнено успешно.
Когда я снова нажимаю кнопку воспроизведения (после того, как воспроизведение завершено). Исключение: недопустимая операция. Исключение перехватывается при попытке try в методе цикла PrintPieces. И появляется текстовое поле с этой трассировкой стека:
at System.Drawing.Image.get_FrameDimensionsList
Ошибка происходит случайно после второго раза, когда я нажимаю кнопку воспроизведения .. (что предполагает условие запуска / несколько потоков, входящих в цикл).
Я прочитал больше об исключении ...:
System.InvalidOperationException: объект в настоящее время используется
в другом месте.
GDI + жалуется, что контекст устройства (DC), который пытается
использование уже "в использовании". С winforms это обычно означает, что есть
рекурсивный Graphics.GetHdc должен соответствовать ReleaseHdc перед любым другим
GetHdc.
Ошибка возникает, если вы рисуете форму из нескольких потоков.
Вероятно, также возникнет исключение между потоками.
Потенциальное решение - не использовать несколько потоков при доступе к форме, включая потоки.
InvalidOperationException используется в случаях, когда не удается вызвать
метод вызван причинами, отличными от недопустимых аргументов. За
Например, InvalidOperationException вызывается:
MoveNext, если объекты коллекции изменены после перечислителя
создан.
Я думаю, что цикл в методе обработчика событий doWork нуждается в защите ... Мне нужно завершить RunAsync до того, как запустится другая runAsync ... и это окажется неудачным ..
Любые решения помогут
ПРИМЕЧАНИЕ. Если вы предоставите больше кода, чем я вам предоставил, вы ничего не добавите ... Я работал над этим с ошибками целый день. Я знаю !!