不积跬步,无以至千里;不积小流,无以成江海。

Dean's blog

  • Join Us on Facebook!
  • Follow Us on Twitter!
  • LinkedIn
  • Subcribe to Our RSS Feed

使用CancellationToken取消Task

假设有一个类似如下的过程:

private static void Print(int max)
{
    for(var i = 0; i < max; i++)
    {
        Thread.Sleep(1000);
        Console.WriteLine($"当前:{i}");
    }
}

//创建Task
var task = Task.Factory.StartNew(() => Print(100));

这里,新增了一个task,每隔1秒在控制台输出一段数据,直到循环结束。如果希望在task执行过程中,可以取消task,可以使用CancellationToken,对代码进行改造,如下:

private static void Print(CancellationToken token, int max)
{
    for(var i = 0; i < max; i++)
    {
        token.ThrowIfCancellationRequested();
        Thread.Sleep(1000);
        Console.WriteLine($"当前:{i}");
    }
}


//创建task
CancellationTokenSource tokenSource = new CancellationTokenSource();
var task = Task.Factory.StartNew(() => Print(tokenSource.Token, 100));

//其它操作

//取消任务
tokenSource.Cancel();

这里,自定义方法中接收一个CancellationToken参数,并调用ThrowIfCancellationRequested()在取消后,中止Task的执行。由于这个是主动检查,所以在调用了Cancel()后,Task并不会立即中止。

如果细心一点,会发现StartNew有一系列方法签名包括了CancellationToken参数的方法,例如:StartNew(Action action, CancellationToken cancellationToken),是否可以使用它直接取消task而不用对现有方法进行改造呢。把上面的方法调整为如下:

private static void Print(int max)
{
    for(var i = 0; i < max; i++)
    {
        Thread.Sleep(1000);
        Console.WriteLine($"当前:{i}");
    }
}


//创建task
CancellationTokenSource tokenSource = new CancellationTokenSource();
var task = Task.Factory.StartNew(() => Print(100), tokenSource.Token);

//其它操作

//取消任务
tokenSource.Cancel();

运行后,发现在tokenSource.Cancel()后,task还在继续执行。如果把代码改造成下,就可以了解StartNew方法的CancellationToken参数的作用了:

private static void Print(int max)
{
    for(var i = 0; i < max; i++)
    {
        Thread.Sleep(1000);
        Console.WriteLine($"当前:{i}");
    }
}


//创建task
CancellationTokenSource tokenSource = new CancellationTokenSource();

//启动前就取消
tokenSource.Cancel();

var task = Task.Factory.StartNew(() => Print(100), tokenSource.Token);

 测试会发现,task并没有启动,因此可以确定,StartNew方法的CancellationToken会决定task是否启动,而想实现task中途取消,则需要自定义方法中使用token.ThrowIfCancellationRequested();才可以。

不允许评论
粤ICP备17049187号-1