Task取消

一:在Thread中做取消操作

声明一个变量取去判断Thread中是否可以退出。

1
2
3
4
5
6
7
8
9
10
11
12
bool res = false;
var task = new Task(()=> {
while (!res)
{
Thread.Sleep(100);
Console.WriteLine("当前Thread={0}正在运行",Thread.CurrentThread.ManagedThreadId);
}
});
task.Start();
Thread.Sleep(1000);
res = true;
Console.Read();

1572915945633

不能让多个线程操作一个共享变量,否则会在release版本中有潜在bug

二:task中有专门的类CancellationTokenSource去处理“任务取消”

1.CancellationTokenSource远比一个变量强的多。

 CancellationTokenSource source = new CancellationTokenSource();
    var task = new Task(() => {
while (!source.IsCancellationRequested)
    {
        Thread.Sleep(100);
         Console.WriteLine("当前Thread={0}正在运行",Thread.CurrentThread.ManagedThreadId);
    }
 },source.Token);
task.Start();
Thread.Sleep(1000);
source.Cancel();

1572916271694

效果同上

2.当任务取消的时候,我希望有一个函数能够被触发,这个触发可以做一些资源的清理,又或者更新数据库信息

   CancellationTokenSource source = new CancellationTokenSource();
    source.Token.Register(()=> {
        //如果当前token被取消,此函数被执行
        Console.WriteLine("当前想线程被取消,可以做资源清理!");
    });
var task = new Task(() => {

    while (!source.IsCancellationRequested)
    {
        Thread.Sleep(100);
         Console.WriteLine("当前Thread={0}正在运行",Thread.CurrentThread.ManagedThreadId);
    }
},source.Token);
task.Start();
Thread.Sleep(1000);
source.Cancel();

1572916548220

3.延时取消:我想2秒之后自动取消,或者N秒

  • source.CancelAfter(new TimeSpan(0,0,0,2));

  • CancellationTokenSource 构造函数: CancellationTokenSource source = new CancellationTokenSource(1000);

  • 取消组合,将CancellationTokenSource 组成一个链表,其中任何一个CancellationTokenSource 被取消,组合也会被取消。var s3=s1&s2;

1
2
3
4
5
6
7
8
CancellationTokenSource source1 = new CancellationTokenSource();
source1.Cancel();
CancellationTokenSource source2 = new CancellationTokenSource();

var source3 = CancellationTokenSource.CreateLinkedTokenSource(source1.Token, source2.Token);


Console.WriteLine("s1={0},s2={1},s3={2}",source1.IsCancellationRequested,source2.IsCancellationRequested,source3.IsCancellationRequested);

加了source1.Cancel();

不加source1.Cancel();

1572917999533

4.ThrowIfCancellationRequested

        CancellationTokenSource source1 = new CancellationTokenSource();
source1.Token.Register(()=> {
               Console.WriteLine("当前想线程被取消,可以做资源清理!");
           });
       var task = Task.Factory.StartNew(() =>
       {
           while (true)
           {
               source1.Token.ThrowIfCancellationRequested();
               Thread.Sleep(100);
               Console.WriteLine("当前Thread={0}正在运行", Thread.CurrentThread.ManagedThreadId);
           }
       }, source1.Token);
       Thread.Sleep(1000);
       source1.Cancel();

       Thread.Sleep(100);
       Console.WriteLine(task.Status);

1572919032504