如何实现可取消的工作线程

5

我正在尝试使用System.Threading.Tasks命名空间中的新线程构造实现可取消的工作线程。 到目前为止,我已经想出了以下实现:

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.StatusTaskStatus.Canceled
我的单元测试表明,在某些情况下,Worker.Status仍然设置为TaskStatus.Running
这是实现可取消工作线程的正确方式吗?
1个回答

5

我认为问题出在你调用的地方

Worker.Wait(_cancellationTokenSource.Token);

那就等待“令牌”被发出信号——因为你刚调用了“Cancel()”,所以它已经被发出信号。如果你将其改为只有
Worker.Wait();

如果执行成功,你将会看见任务的状态为RanToCompletion。如果没有抛出OperationCanceledException异常,你将不会看到已取消的状态。如果你想要改变RunTasks方法的调用方式

cancellationToken.ThrowIfCancellationRequested()

最后,你需要在Stop中捕获一个AggregateException - 但是最终你会看到一个Canceled的状态。

至少,这就是我的实验结果 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接