C#异步任务取消
c# async task cancellation
我在掌握任务和取消标记时遇到了一些问题。我制作了一个如下所示的程序:
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 个任务(尽管当我不包括 Thread.Sleep()
时,for
循环似乎 运行 在任务开始之前?) .当我 运行 程序时,None 的任务被取消了。另外让我烦恼的是...调用 token.Cancel()
时我真正取消了什么任务?我如何选择要杀死 5 个任务中的哪一个?我可以通过它的变量定义每个任务,但我无法访问它的 CancellationRequested
属性,因为它是由 CancellationToken
触发的。那我需要 5 个不同的代币吗?
None of the tasks get ever cancelled when I run the program.
那是因为您只在任务的开始 时才检查取消标记。一旦通过了第一个 token.IsCancellationRequested
检查,取消令牌将不会执行任何操作。如果您将支票移动到循环中,如下所示:
while (sw.ElapsedMilliseconds < time)
{
if (token.IsCancellationRequested)
{
Console.WriteLine("Cancelled");
return;
}
Thread.SpinWait(1000);
}
...然后您会看到任务做出适当的反应。
Also what is bugging me is...what task am I really cancelling when calling token.Cancel()
?
您不是在取消任务 - 您是在取消取消标记。 观察到取消令牌的任何任务都将被取消(或完成,或采取任何行动)但任务和令牌之间没有直接关联。
当我们谈论 "cancelling a task" 时,我们实际上是指 "cancelling a token which we believe the task is observing"。
我在掌握任务和取消标记时遇到了一些问题。我制作了一个如下所示的程序:
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 个任务(尽管当我不包括 Thread.Sleep()
时,for
循环似乎 运行 在任务开始之前?) .当我 运行 程序时,None 的任务被取消了。另外让我烦恼的是...调用 token.Cancel()
时我真正取消了什么任务?我如何选择要杀死 5 个任务中的哪一个?我可以通过它的变量定义每个任务,但我无法访问它的 CancellationRequested
属性,因为它是由 CancellationToken
触发的。那我需要 5 个不同的代币吗?
None of the tasks get ever cancelled when I run the program.
那是因为您只在任务的开始 时才检查取消标记。一旦通过了第一个 token.IsCancellationRequested
检查,取消令牌将不会执行任何操作。如果您将支票移动到循环中,如下所示:
while (sw.ElapsedMilliseconds < time)
{
if (token.IsCancellationRequested)
{
Console.WriteLine("Cancelled");
return;
}
Thread.SpinWait(1000);
}
...然后您会看到任务做出适当的反应。
Also what is bugging me is...what task am I really cancelling when calling
token.Cancel()
?
您不是在取消任务 - 您是在取消取消标记。 观察到取消令牌的任何任务都将被取消(或完成,或采取任何行动)但任务和令牌之间没有直接关联。
当我们谈论 "cancelling a task" 时,我们实际上是指 "cancelling a token which we believe the task is observing"。