假设我有一个List<Task>
,它可以帮助我根据索引管理所有任务:
private List<Task> tasks = new List<Task>(new Task[3]);
当应用程序启动时,将显示一个菜单,用户可以简单地选择可以启动的任务:
public void Menu()
{
Console.WriteLine("1. Task");
Console.WriteLine("2. Task");
Console.WriteLine("3. Task");
Console.WriteLine("0. Exit");
ConsoleKeyInfo input;
do
{
input = Console.ReadKey();
Console.WriteLine();
switch (input.Key)
{
case ConsoleKey.NumPad1:
StartTask(1);
break;
case ConsoleKey.NumPad2:
StartTask(2);
break;
case ConsoleKey.NumPad3:
StartTask(3);
break;
}
} while (input.Key != ConsoleKey.NumPad0);
}
在方法StartTask
中,我传递了Task
的数量来执行,这是逻辑:
public void StartTask(int instance)
{
int index = instance - 1;
//Task not yet instantiated, create new one
if(tasks.ElementAtOrDefault(index) == null)
{
//Make a new cancellation token
cts.Insert(index, new CancellationTokenSource());
tasks.Insert(index, new Task(async () =>
{
await foo.DoWork(cts[index].Token);
}, cts[index].Token));
if(!tasks[index].Status.Equals(TaskStatus.Running))
{
tasks[index].Start();
}
}
}
如您所见,我还有一个List<CancellationTokenSource> cts
可以帮助我终止任务。 Cancel
方法位于上面的另一个菜单中。
现在问题很明显:我无法执行此操作,因为检查是在包含以下内容的await
的{{1}}操作之前执行的:
DoWork();
本质上:如何停止用public class Foo
{
private async Task DoWorkAsync(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
string newData = DateTime.Now.ToLongTimeString();
Console.WriteLine(newData);
await Task.Delay(200);
}
}
}
执行Task
的{{1}}?
如果在启动之后执行停止,则作为参数传递的令牌无法更改值。本质上,loop
的值仅在CancellationToken
类上下文中更改,而不在传递的参数中更改。
答案 0 :(得分:1)
将取消令牌传递给DoWorkAsync。 并在“ while”循环中使用它作为条件。
while(!token.IsCancellationRequested)
{
await Task.Delay(200, token);
}
“令牌”应作为参数传递。 老实说,我认为您的解决方案中有太多冗余代码...
如何使用取消令牌来源取消任务:
void CancelTask(int taskNumber)
{
int index = taskNumber - 1;
cts[index].Cancel();
}
此代码会将您在循环中使用的'token'的'IsCancellationRequested'标志设置为'true'。