Question

I want to cancel a thread and and run another one just after. Here is my code:

private void ResetMedia(object sender, RoutedEventArgs e)
{
        cancelWaveForm.Cancel(); // cancel the running thread
        cancelWaveForm.Token.WaitHandle.WaitOne(); // wait the end of the cancellation
        cancelWaveForm.Dispose();

        //some work

        cancelWaveForm = new CancellationTokenSource(); // creating a new cancellation token
        new Thread(() => WaveFormLoop(cancelWaveForm.Token)).Start(); // starting a new thread
}

When I call this method, the first thread doesn't stop and the second one start running...
But if I skip the two last line it works :

private void ResetMedia(object sender, RoutedEventArgs e)
{
        cancelWaveForm.Cancel(); // cancel the running thread
        cancelWaveForm.Token.WaitHandle.WaitOne(); // wait the end of the cancellation
        cancelWaveForm.Dispose();

        //some work

        //cancelWaveForm = new CancellationTokenSource(); // creating a new cancellation token
        //new Thread(() => WaveFormLoop(cancelWaveForm.Token)).Start(); // starting a new thread
}

Why it doesn't stop?

Edit 1 :

private void WaveFormLoop(CancellationToken cancelToken)
{
        try
        {
            cancelToken.ThrowIfCancellationRequested();
            //some stuff to draw a waveform
        }
        catch (OperationCanceledException) 
        {
            //Draw intitial Waveform
            ResetWaveForm();
        }
}
Was it helpful?

Solution

Using CancellationTokens is called "Co-operative cancelation" because the code must co-operate with the cancelation action. You only check once at the start of the function, if the cancelation happens after that check the cancelation never happens.

Based on the name of the function I assume there is a loop of some kind in it. Your function needs to look like this instead.

private void WaveFormLoop(CancellationToken cancelToken)
{
        try
        {
            while(someCondition) //Replace this with your real loop structure, I had to guess
            {
                cancelToken.ThrowIfCancellationRequested();
                //some stuff to draw a waveform
            }
        }
        catch (OperationCanceledException) 
        {
            //Draw intitial Waveform
            ResetWaveForm();
        }
}

Now it checks to see if cancelation happened every iteration of the loop. If the loop body takes a very long time to process you may want more than one call inside the loop.

private void WaveFormLoop(CancellationToken cancelToken)
{
        try
        {
            while(someCondition) //Replace this with your real loop structure, I had to guess
            {
                cancelToken.ThrowIfCancellationRequested();

                Thread.Sleep(1000); //Fake doing work

                cancelToken.ThrowIfCancellationRequested();

                Thread.Sleep(1000); //Fake doing more work
            }
        }
        catch (OperationCanceledException) 
        {
            //Draw intitial Waveform
            ResetWaveForm();
        }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top