C#多线程学习笔记六

Thread中的取消操作

isStop变量判断thread是否可以退出

bool isStop = false;
Thread thread = new Thread(() =>
{
    
    
while (!isStop) 
{
    
    
Thread.Sleep(100);
        Console.WriteLine("当前Thread正在运行。");
     }
});
thread.Start();
Thread.Sleep(1000);
isStop = true;

运行结果:thread运行了1秒后停止。
这样存在一个问题,让多个线程操作一个共享变量,在release版本那种会存在潜在bug。bug见笔记二中的release和debug的性能差异

Task中的取消操作

CancellationTakenSource类远比使用isStop变量要强的多。

使用cancel实现isStop同样的功能

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

运行结果:与使用isStop结果一样
那么CancellationTakenSource类比使用isStop变量要强在哪里?
a. 当任务取消的时候,若希望有一个函数能被触发,这个触发可以做一些资源清理,又或者是更新数据库信息。当task被取消的同时就会执行register中的回调函数。

CancellationTokenSource source = new CancellationTokenSource();
source.Token.Register(() =>
{
    
    
   //如果当前的Source被取消,此函数会执行
   Console.WriteLine("如果当前source被取消,现在可以做资源清理了。");
});
var task = Task.Factory.StartNew(() =>
{
    
    
   while (!source.IsCancellationRequested)
   {
    
    
      Thread.Sleep(100);
      Console.WriteLine("当前Thread={0},正在运行。", Thread.CurrentThread.ManagedThreadId);
   }
}, source.Token);

执行结果:
在这里插入图片描述
b. 延时取消。
如果想N秒后自动取消,例如调用webservice接口,如果很久没响应,应该设置若干秒后自动取消。
方法一:CancelAfter

source.CancelAfter(new TimeSpan(0,0,0,1));

方法二:在CancellationTokenSource的构造函数中设置时间

CancellationTokenSource source = new CancellationTokenSource(1000);

c. 取消的组合

var combineSource = CancellationTokenSource.CreateLinkedTokenSource(source1.Token, source2.Token);  
Console.WriteLine("s1 = {0}, s2 = {1}, s = {2}",source1.IsCancellationRequested,
source2.IsCancellationRequested,combineSource.IsCancellationRequested);

输出结果:s1 = True, s2 = False, s = True。
可以看出 s = s1 && s2

d. ThrowIfCancellationRequested
如果一个任务被取消,会抛出一个异常。

CancellationTokenSource source = new CancellationTokenSource();
var task = Task.Factory.StartNew(() =>
{
    
    
 while (true)
 {
    
    
     try
     {
    
    
         source.Token.ThrowIfCancellationRequested();
     }catch(Exception)
     {
    
    
           //do something
     }
 }
}, source.Token);

猜你喜欢

转载自blog.csdn.net/Z960515/article/details/113438686