为什么任务取消使用新任务再次运行?

时间:2014-07-15 10:12:51

标签: task-parallel-library

我有一个关于Task的例子。我启动一个新的任务来执行一个LongTask并在我取消任务之后并在启动一个新任务后再次执行LongTask。但是TaskA运行不正常。它运行任务取消和新任务的工作。

如何立即运行新任务 并取消已取消的任务?

这是我的代码:

class Program
    {
        private static CancellationTokenSource tokenSource = new CancellationTokenSource();
        static void Main(string[] args)
        {
            Program a = new Program();
            Task.Factory.StartNew(() => a.LongTask(), tokenSource.Token);
            Console.ReadLine();

            //After enter
            tokenSource.Cancel();
            //Create new CancellationTokenSource to make Task continue run
            tokenSource = new CancellationTokenSource();
            Task.Factory.StartNew(() => a.LongTask(), tokenSource.Token);
            Console.ReadLine();
        }

        public void LongTask()
        {
            StringBuilder display = new StringBuilder();
            while (!tokenSource.IsCancellationRequested)
            {
                display.Append("1");
                Console.WriteLine(display);
                Thread.Sleep(1000);
            }
        }
    }

1 个答案:

答案 0 :(得分:2)

我将想象出第一个任务正在睡觉时会发生什么

while (!tokenSource.IsCancellationRequested)
{
    display.Append("1");
    Console.WriteLine(display);
    Thread.Sleep(1000);
    // tokenSource.Cancel();
    // tokenSource = new CancellationTokenSource();
    // Task.Factory.StartNew second task
}

然后在睡眠超时后,任务#1继续其循环以检查tokenSource.IsCancellationRequested false(因为此标记是新标记)。

现在您了解为什么两个任务以这种方式运行。让我们试试我的代码:

static void Main(string[] args)
{
    var a = new Program();
    var token = new CancellationTokenSource();
    Task t1 = Task.Factory.StartNew(() => a.LongTask("#1", token1.Token), token1.Token);

    Console.ReadLine();

    token1.Cancel();
    token = new CancellationTokenSource();
    Task.Factory.StartNew(() => a.LongTask("#2", token2.Token), token2.Token);
    Console.ReadLine();
}

public void LongTask(string name, CancellationToken killer)
{
    var display = new StringBuilder();
    while (!killer.IsCancellationRequested)
    {
        display.Append("1");
        Console.WriteLine("{0} says: {1}",name, display);
                Thread.Sleep(1000);
    }
}

这里的技巧是为每个任务提供一个不同的令牌,而不是共享相同的静态令牌实例。