Прерывание темы (Backgroundworker) .. нужен совет - PullRequest
1 голос
/ 21 июля 2011
        public void ReplayGame()
    {

        if (Class2.replayIsOn)
        {

            if (!backgroundWorker1.IsBusy)
            {
                backgroundWorker1.RunWorkerAsync();
            }
        }                 
    }

Я хочу отменить / остановить backgroundwoker1, как только функция завершится .. событие backgroundworker запускается на несколько секунд и останавливается .. когда оно останавливается, я хочу, чтобы оно закончилось !! ..

Как я могу достичь этой задачи /?без получения недопустимых исключений операций, которые я получаю сейчас

ОБНОВЛЕНИЕ:

    public void ReplayGame()
    {

        if (Class2.replayIsOn)
        {
            replay = serializeMeh.giveBackDictionary();
            backgroundWorker1.WorkerSupportsCancellation = true;
            backgroundWorker1.RunWorkerAsync();
        }        
    }



    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {

        int[] makeSelfMoves = new int[4];
        if (!backgroundWorker1.CancellationPending)
        {
            lock (replay)
            {
                foreach (KeyValuePair<int, int[]> item in replay)// count should be more than 2
                {
                    if (backgroundWorker1.CancellationPending)
                    {
                        break;
                    }
                    makeSelfMoves = replay[item.Key];
                    codeFile.ExecuteAll(makeSelfMoves[0], makeSelfMoves[1], makeSelfMoves[2], makeSelfMoves[3]);
                    PrintPieces(codeFile.PieceState()); Invalid operation exception is thrown here when chess pieces are drawn on the screen ... Two threads enter the loop simultaneously..:(...Invalid operation exception


                    System.Threading.Thread.Sleep(1000);
                }
                Class2.counter = serializeMeh.serializedCounter;
                Class2.replayIsOn = false;
                Game.WasntSerialized = true;
            }
        }
        backgroundWorker1.CancelAsync();
    }

Ответы [ 5 ]

3 голосов
/ 21 июля 2011

Проверяли ли вы, что работник поддерживает отмену?

backgroundWorker1.WorkerSupportsCancellation = true;

Если вы явно не установили его и звоните

backgroundWorker1.CancelAsync();

InvalidOperationException будет сгенерировано, потому что по умолчанию работник не поддерживает асинхронное отмену.

UPDATE
Это просто свойство, которое проверяет состояние работников, если вам нужно отменить работу, вам нужно позвонить backgroundWorker1.CancelAsync();

См. Образец здесь

2 голосов
/ 21 июля 2011

Вы только проверяете, ожидает ли отмена отмены один раз, прежде чем начать цикл, а затем никогда не проверяете его снова.Вам нужно проверить каждую итерацию цикла:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    int[] makeSelfMoves = new int[4];
    {
        lock (replay)
        {
            foreach (KeyValuePair<int, int[]> item in replay)// count should be more than 2
            {
                makeSelfMoves = replay[item.Key];
                codeFile.ExecuteAll(makeSelfMoves[0], makeSelfMoves[1], makeSelfMoves[2], makeSelfMoves[3]);
                PrintPieces(codeFile.PieceState());

                if (backgroundWorker1.CancellationPending)
                    break;

                System.Threading.Thread.Sleep(1000);
            }

            Class2.counter = serializeMeh.serializedCounter;
            Class2.replayIsOn = false;
            Game.WasntSerialized = true;
        }
    }
}
1 голос
/ 21 июля 2011

Я хотел бы отметить, что:

if (backgroundWorker1.IsBusy)              
{                    
backgroundWorker1.CancelAsync();              
}                
if (!backgroundWorker1.IsBusy)              
{
replay = serializeMeh.giveBackDictionary();                  backgroundWorker1.RunWorkerAsync();              
}  

действительно должно быть:

if (backgroundWorker1.IsBusy)              
{                    
backgroundWorker1.CancelAsync();              
}                
else
{
replay = serializeMeh.giveBackDictionary();                  backgroundWorker1.RunWorkerAsync();              
}
0 голосов
/ 21 июля 2011

Мне кажется, что отмена BackgroundWorker в конце обратного вызова DoWork не нужна? По замыслу BackgroundWorker перестает работать, когда завершается обратный вызов DoWork; в этот момент событие RunWorkerCompleted возникает так же, как и после вызова CancelAsync().

Если я не пропустил что-то в исходном вопросе, я не вижу различия в поведении по умолчанию и почему предпочтительнее отменить работника?

0 голосов
/ 21 июля 2011

Сначала нужно позвонить CancelAsync.Затем вам нужно проверить свойство CancellationPending, используя охранное предложение с оператором return.

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    // A bunch of stuff here.

    if (backgroundWorker1.CancellationPending) return;

    // A bunch of stuff here.
}
...