简体   繁体   English

如何停止异步任务?

[英]How to stop an async task?

Suppose that I have a List<Task> which help me to manage all the task based on index:假设我有一个List<Task>可以帮助我根据索引管理所有任务:

private List<Task> tasks = new List<Task>(new Task[3]);

When the application start a menu is displayed, and the user can select which task can start, simply:当应用程序启动时会显示一个菜单,用户可以选择可以启动的任务,只需:

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);
}

inside the method StartTask I pass the number of Task to execute, this is the logic:在方法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();
        }
    }
}

as you can see I also have a List<CancellationTokenSource> cts which help me to terminate the task.如您所见,我还有一个List<CancellationTokenSource> cts可帮助我终止任务。 The Cancel method is placed in another menu like above. Cancel方法放置在另一个菜单中,如上所示。

Now the problem is pretty clear: I can't do that because the checking is executed before the await operation of DoWork();现在问题很清楚了:我不能这样做,因为检查是在DoWork();await操作之前执行的DoWork(); that contains this:包含这个:

public class Foo
{
     private async Task DoWorkAsync(CancellationToken token)
     {
         while (!token.IsCancellationRequested)
         {
             string newData = DateTime.Now.ToLongTimeString();

             Console.WriteLine(newData);
              await Task.Delay(200);
         }
     }
}

essentially: how can I stop the Task that execute the loop with the CancellationToken ?本质上:如何停止使用CancellationToken执行loopTask

The token passed as parameter cannot change the value if the stop is executed later the start.如果在启动后执行停止,则作为参数传递的令牌不能更改该值。 Essentially the value of IsCancellationRequested is changing only in the Task class context, not in the argument passed.本质上, IsCancellationRequested的值仅在Task类上下文中更改,而不是在传递的参数中更改。

Pass cancellation token to DoWorkAsync.将取消令牌传递给 DoWorkAsync。 And use it in 'while' loop as a condition.并在 'while' 循环中使用它作为条件。

while(!token.IsCancellationRequested)
{ 
   await Task.Delay(200, token); 
}

'token' should be passed as a parameter. 'token' 应该作为参数传递。 To be honest, I think there is too much redundant code in your solution ...老实说,我认为您的解决方案中有太多冗余代码......

How to cancel task using cancellation token source:如何使用取消令牌源取消任务:

void CancelTask(int taskNumber)
{
   int index = taskNumber - 1;
   cts[index].Cancel();
}

This code will set 'IsCancellationRequested' flag of 'token' you use in the loop into 'true'.此代码会将您在循环中使用的“令牌”的“IsCancellationRequested”标志设置为“true”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM