Как реализовать отменимый рабочий поток

Я пытаюсь реализовать отменимый рабочий поток с помощью новых конструкций поточной обработки в Системе. Поточная обработка. Пространство имен задач. До сих пор я имею, придумали эту реализацию:

public sealed class Scheduler
{
    private CancellationTokenSource _cancellationTokenSource;
    public System.Threading.Tasks.Task Worker { get; private set; }

    public void Start()
    {
        _cancellationTokenSource = new CancellationTokenSource();

        Worker = System.Threading.Tasks.Task.Factory.StartNew(
            () => RunTasks(_cancellationTokenSource.Token),
             _cancellationTokenSource.Token
        );
    }

    private static void RunTasks(CancellationToken cancellationToken)
    {
        while (!cancellationToken.IsCancellationRequested)
        {
            Thread.Sleep(1000); // simulate work
        }
    }

    public void Stop()
    {
        try
        {
            _cancellationTokenSource.Cancel();
            Worker.Wait(_cancellationTokenSource.Token);
        }
        catch (OperationCanceledException)
        {
            // OperationCanceledException is expected when a Task is cancelled.
        }
    }
}

Когда Stop() возвраты я ожидаю Worker.Status быть TaskStatus.Canceled.
Мои модульные тесты показали это при определенных условиях Worker.Status остается установленным на TaskStatus.Running.

Действительно ли это - корректный способ реализовать отменимый рабочий поток?

5
задан Arnold Zokas 31 May 2010 в 09:02
поделиться

1 ответ

Я считаю, что проблема в вашем звонке на

Worker.Wait(_cancellationTokenSource.Token);

, который ожидает сигнала токена - что уже есть, потому что вы только что вызвали Cancel () . Если вы измените это значение на

Worker.Wait();

, то, я думаю, вы увидите состояние RanToCompletion . Вы не увидите "Отменено", потому что ваша задача не создает исключение OperationCanceledException . Если вы измените свой метод RunTasks на вызов

cancellationToken.ThrowIfCancellationRequested()

в конце, тогда вам нужно будет перехватить AggregateException в Stop - но тогда вы см. в конце состояние Отменено .

По крайней мере, это то, что показывают мои эксперименты :)

5
ответ дан 14 December 2019 в 19:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: