如何停止异步任务?

时间:2018-10-31 11:55:18

标签: c# task

假设我有一个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类上下文中更改,而不在传递的参数中更改。

1 个答案:

答案 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'。