【发布时间】:2014-03-29 19:04:06
【问题描述】:
我有一个始终被阻止的任务,并且我有一个 CancellationToken 传递给它,用于取消任务。但是,Continuation 任务永远不会执行,它设置为在 Task 取消时执行。代码是:
_tokenSrc = new CancellationTokenSource();
var cnlToken = _tokenSrc.Token;
Task.Run(() =>
// _stream.StartStream() blocks forever
_stream.StartStream(), cnlToken)
.ContinueWith(ant =>
{
_logger.Warn("Stream task cancellation requested, stopping the stream");
_stream.StopStream();
_stream = null;
_logger.Warn("Stream stopped and task cancelled");
}, TaskContinuationOptions.OnlyOnCanceled);
稍后在代码的其他地方...
_tokenSrc.Cancel();
我必须为 _stream.StartStream() 使用任务的原因是这个调用永远阻塞(我无法控制的 api,请注意 _stream 是指从 web 服务流数据的第三方 Api)所以我必须在另一个线程上调用它。
取消任务的最佳方法是什么?
【问题讨论】:
-
不确定您要在这里做什么...
_tokenSrc.Cancel();是取消任务的正确方法。但是,您还应该监视此令牌以在您的任务中取消。它不会自己发生。通过使用全局范围的流,您在这里做着可怕的事情。这样做没有意义,因为您的延续任务可能发生在主任务中。归根结底,你想做什么?为什么你需要任务?请通过编辑上面的问题来回答这两个问题。 -
该流是我正在使用的一个 API,它的设计方式很糟糕,我无法控制。由于对 _stream.StartStream() 的调用永远不会返回,因此我无法在循环中检查 cnlToken 的状态,您将如何实现它?
-
@MaYaN:如果您无法检查取消,则不能使用 TPL 取消。取消令牌只是实现任务取消的一种手段,它并不强制执行。是否有 API 可以取消来自不同线程的流?
-
@jdv-JandeVaan:感谢您的回复,我开始得出相同的结论 :-) 我需要终止清理任务。我可能会旋转一个启动流的子任务,然后定期检查父任务上的 IsCancellationRequested。
-
@Neolisk:Tnx,这是我打算避免的备用计划:-)
标签: c# task-parallel-library cancellation-token