什么是“cancellationToken”在TaskFactory.StartNew()中用于什么?
http://msdn.microsoft.com/en-us/library/dd988458.aspx
UPD:
那么,让我们讨论这篇文章:http://msdn.microsoft.com/en-us/library/dd997396.aspx
我稍微更改了该代码:
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;
Thread.Sleep(5000);
while (moreToDo)
{
// Poll on this property if you have to do
// other cleanup before throwing.
if (ct.IsCancellationRequested)
{
Console.WriteLine("exit");
// Clean up here, then...
ct.ThrowIfCancellationRequested();
}
}
}, tokenSource2.Token); // this parameter useless
Console.WriteLine("sleep");
Thread.Sleep(2000);
Console.WriteLine("cancel");
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();
}
UPD:嗯,这仅更改task.IsCanceled
,恕我直言,这是无用的,因为我仍然应该手动实现所有操作。
http://msdn.microsoft.com/en-us/library/dd988458.aspx
UPD:
so, let's discuss this article then: http://msdn.microsoft.com/en-us/library/dd997396.aspx
I've changed that code a little:
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;
Thread.Sleep(5000);
while (moreToDo)
{
// Poll on this property if you have to do
// other cleanup before throwing.
if (ct.IsCancellationRequested)
{
Console.WriteLine("exit");
// Clean up here, then...
ct.ThrowIfCancellationRequested();
}
}
}, tokenSource2.Token); // this parameter useless
Console.WriteLine("sleep");
Thread.Sleep(2000);
Console.WriteLine("cancel");
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();
}
UPD: Well, this changes only task.IsCanceled
, which is imho useless, due to I still ought to implement all manually.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
由于评论,我发布了另一个答案。
考虑以下代码:
即使在任务实际启动之前调用
tokenSource.Cancel()
,您仍然会从线程池中分配一个工作线程,因此您会浪费一些系统资源。但是,当您在
Task.Factory.StartNew
中指定 token 参数时,任务将立即取消,而不分配工作线程。Due to comments, I'm posting another answer.
Consider the following code:
Even if the call
tokenSource.Cancel()
is issued before the task was actually started, you'll still allocate a worker thread from thread pool, so you'll waste some system resources.But when you specify token argument in
Task.Factory.StartNew
, the task will be cancelled immediately, without allocating a worker thread.取消任务仍然是合作的。您不希望线程在某些关键操作中被终止。你需要检查一下。
CancellationTokens 比诸如
ManualResetEvent
之类的更简单的结构更好,因为您可以级联或组合它们,例如,您可以将它们用于整个应用程序关闭,也可以将其与一个用于取消的组合一项特定任务。该任务只需查看一个CancellationToken
,但您可以从任一CancellationTokenSource
取消它。Cancellation with Tasks is still cooperative. You wouldn't want a thread to be killed in the middle of some critical operation. You need to check for it.
CancellationTokens are better than simpler constructs like a
ManualResetEvent
for signalling shutdown of an operation because you can cascade or combine them, for example, you can have one for overall application shutdown and you can combine it with one for canceling a particular task. The task only has to look at the oneCancellationToken
but you can cancel it from eitherCancellationTokenSource
.