Dmitry Makovetskiyd
Dmitry Makovetskiyd

Reputation: 7053

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

Upvotes: 1

Views: 2614

Answers (5)

sellmeadog
sellmeadog

Reputation: 7517

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?

Upvotes: 0

Security Hound
Security Hound

Reputation: 2551

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

Upvotes: 1

Dour High Arch
Dour High Arch

Reputation: 21712

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

Upvotes: 2

Brian Gideon
Brian Gideon

Reputation: 48949

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

Upvotes: 0

oleksii
oleksii

Reputation: 35905

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

Upvotes: 3

Related Questions