0

我想取消一个线程并在之后运行另一个线程。这是我的代码:

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
}

当我调用此方法时,第一个线程不会停止,第二个线程开始运行......
但如果我跳过最后两行它可以工作:

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
}

为什么停不下来?

编辑 1:

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

1 回答 1

8

使用 CancellationTokens 称为“合作取消”,因为代码必须与取消操作合作。您只在函数开始时检查一次,如果在此之后发生取消,则检查取消永远不会发生。

根据函数的名称,我假设其中有某种循环。您的函数需要看起来像这样。

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

现在它检查是否在循环的每次迭代中都发生了取消。如果循环体需要很长时间来处理,您可能需要在循环内进行多个调用。

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();
        }
}
于 2014-03-08T19:00:44.420 回答