Я пытаюсь реализовать отменимый рабочий поток с помощью новых конструкций поточной обработки в Системе. Поточная обработка. Пространство имен задач. До сих пор я имею, придумали эту реализацию:
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
.
Действительно ли это - корректный способ реализовать отменимый рабочий поток?
Я считаю, что проблема в вашем звонке на
Worker.Wait(_cancellationTokenSource.Token);
, который ожидает сигнала токена - что уже есть, потому что вы только что вызвали Cancel ()
. Если вы измените это значение на
Worker.Wait();
, то, я думаю, вы увидите состояние RanToCompletion
. Вы не увидите "Отменено", потому что ваша задача не создает исключение OperationCanceledException
. Если вы измените свой метод RunTasks
на вызов
cancellationToken.ThrowIfCancellationRequested()
в конце, тогда вам нужно будет перехватить AggregateException
в Stop
- но тогда вы см. в конце состояние Отменено
.
По крайней мере, это то, что показывают мои эксперименты :)