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
}

このメソッドを呼び出すと、最初のスレッドは停止せず、2 番目のスレッドが実行を開始します...
しかし、最後の 2 行をスキップすると動作します:

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 に答える