我正在尝试使用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.Status
为TaskStatus.Canceled
我的单元测试表明,在某些情况下,Worker.Status
仍设置为TaskStatus.Running
。
这是实现可取消工作线程的正确方法吗?
答案 0 :(得分:5)
我认为问题出在您的
号召唤中Worker.Wait(_cancellationTokenSource.Token);
正在等待令牌发出信号 - 因为你刚刚调用了Cancel()
。如果您将其更改为
Worker.Wait();
然后我相信你会看到状态RanToCompletion
。你不会看到已取消,因为你的任务没有抛出OperationCanceledException
。如果您更改了RunTasks
方法以致电
cancellationToken.ThrowIfCancellationRequested()
最后,您需要在AggregateException
中抓住Stop
- 但最后您会看到状态Canceled
。
至少,这就是我的实验所示:)