我有一个始终被阻止的任务,我有一个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)所以我不得不在另一个线程上调用它。
取消任务的最佳方法是什么?
答案 0 :(得分:1)
[UPDATE]
我将代码更改为下面修复了问题:
Task.Run(() =>
{
var innerTask = Task.Run(() => _stream.StartStream(), cToken);
innerTask.Wait(cToken);
}, cToken)
.ContinueWith(ant =>
{
_logger.Warn("Stream task cancellation requested, stopping the stream");
_stream.StopStream();
_stream = null;
_logger.Warn("Stream stopped and task cancelled");
}, TaskContinuationOptions.OnlyOnCanceled);
答案 1 :(得分:0)
您可以使用Register
上的CancellationToken
方法注册将在请求取消时调用的委托。在委托中,您调用解锁阻止操作的方法。
类似的东西:
_tokenSrc = new CancellationTokenSource();
var cnlToken = _tokenSrc.Token;
var task = Task.Factory.StartNew(() =>
{
using(var tokenReg = cnlToken.Register(() =>
{
_logger.Warn("Stream task cancellation requested, stopping the stream");
_stream.StopStream();
_stream = null;
_logger.Warn("Stream stopped and task cancelled");
}))
{
_stream.StartStream(), cnlToken)
}
}, cnlToken);
答案 2 :(得分:-1)
此处清楚地描述了如何使用取消令牌:http://msdn.microsoft.com/en-us/library/dd997396(v=vs.110).aspx,其中包含建议的模式。
我会在页面出现故障时报告示例:
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main()
{
var tokenSource2 = new CancellationTokenSource();
CancellationToken ct = tokenSource2.Token;
var task = Task.Factory.StartNew(() =>
{
// Were we already canceled?
ct.ThrowIfCancellationRequested();
bool moreToDo = true;
while (moreToDo)
{
// Poll on this property if you have to do
// other cleanup before throwing.
if (ct.IsCancellationRequested)
{
// Clean up here, then...
ct.ThrowIfCancellationRequested();
}
}
}, tokenSource2.Token); // Pass same token to StartNew.
tokenSource2.Cancel();
// Just continue on this thread, or Wait/WaitAll with try-catch:
try
{
task.Wait();
}
catch (AggregateException e)
{
foreach (var v in e.InnerExceptions)
Console.WriteLine(e.Message + " " + v.Message);
}
Console.ReadKey();
}
}
这里有一个更深入的例子:http://msdn.microsoft.com/en-us/library/dd537607(v=vs.110).aspx但第一个应该足够你的场景。