2016-10-28 201 views
0

我在处理任务和取消令牌时遇到了一些问题。我做了一个程序,它看起来像这样:(?虽然我不包括Thread.Sleep()for循环似乎运行之前,任务甚至开始)c#异步任务取消

static void Main(string[] args) 
{ 

    CancellationTokenSource token = new CancellationTokenSource(); 
    Stopwatch stop = new Stopwatch(); 
    stop.Start(); 

    for (int i = 0; i < 5; i++) 
    { 
     //Thread.Sleep(1000); 
     Task.Factory.StartNew(() => myLongTask(token.Token, (i + 1) * 1000)); 
    } 
    while (true) 
    { 
     Thread.SpinWait(1000); 
     if (stop.ElapsedMilliseconds > 3000) 
     { 
      token.Cancel(); 
     } 
    } 
} 

public static void myLongTask(CancellationToken token, int time) 
{ 
    if (token.IsCancellationRequested) 
    { 
     Console.WriteLine("Cancelled"); 
     return; 
    } 
    var sw = Stopwatch.StartNew(); 
    Console.WriteLine($"Task {time/1000} started"); 
    while (sw.ElapsedMilliseconds < time) 
     Thread.SpinWait(1000); 
    Console.WriteLine($"Task {time/1000} ended"); 

} 

我同时运行5个任务。当我运行程序时,任何任务都不会取消。另外什么是窃听我是...什么任务我真的取消时调用token.Cancel()?我怎样才能选择我要杀的5个任务中的哪一个?我可以通过它的变量来定义每个任务,但我不能访问它的属性,因为它是由CancellationToken触发的。我需要5个不同的标记吗?

回答

8

当我运行该程序时,任何任务都不会取消。

这是因为您只在任务的开始处检查取消标记。一旦它通过了第一个token.IsCancellationRequested检查,取消令牌就什么也不做。如果你移动你的支票存入你的循环,像这样:

while (sw.ElapsedMilliseconds < time) 
{ 
    if (token.IsCancellationRequested) 
    { 
     Console.WriteLine("Cancelled"); 
     return; 
    } 
    Thread.SpinWait(1000); 
} 

...然后你会看到任务作出适当的反应。

另外什么是窃听我是...什么任务,我真的取消时调用token.Cancel()

您不取消任务 - 取消取消令牌。 观察到的任何任务取消标记将被取消(或完成,或执行任何操作),但任务与标记之间没有直接关联。

当我们谈论“取消任务”时,我们的意思是“取消我们相信任务正在观察的令牌”。

+0

但是,如果我有5个不同的任务,只有一个'token.Cancel()'...那么它显然取消所有5个?如果我想杀死一个特定的任务,我是否需要一个令牌列表? – Norgul

+0

@Norgul:是的,你会的。或者至少,你需要5个不同的标记和*某种方式来知道你想要停止的任务正在观察哪一个。 –