简体   繁体   中英

Aborting a thread (Backgroundworker).. need an advice

        public void ReplayGame()
    {

        if (Class2.replayIsOn)
        {

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

I wan to cancel/stop backgroundwoker1 as soon as the function ends.. the backgroundworker event runs for a few seconds and stops..when it stops I want it to end....

How can I achieve that task/? without getting any invalid operation exceptions that i am getting now

UPDATE:

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

Did you check that the worker support cancellation?

backgroundWorker1.WorkerSupportsCancellation = true;

If you haven't explicitly set it and you call

backgroundWorker1.CancelAsync();

InvalidOperationException will be thrown, because by default worker doesn't support asynch cancellation.

UPDATE
That's just the property that checks the workers's state, if you need to cancel the work you need to call backgroundWorker1.CancelAsync();

See a sample here

You are only checking to see if cancellation is pending once before you start your loop, then never check it again. You need to check every iteration through the loop:

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

I would like to point out that:

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

really should be:

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

First you need to call CancelAsync . Then you need to check the CancellationPending property using a guard clause with a return statement.

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

    if (backgroundWorker1.CancellationPending) return;

    // A bunch of stuff here.
}

It seems to me that cancelling the BackgroundWorker at the end of the DoWork callback is unnecessary? By design, the BackgroundWorker does stop working when the DoWork callback exits; at this point the RunWorkerCompleted event is raised just like it would be after calling CancelAsync() .

Unless I'm missing something in the original question, I don't see how the default behavior is any different and why cancelling the worker would be preferred?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM