发现个好玩的东东,CancellationTokenSource,可以用来对线程的中断进行控制,原先一直使用 static bool run 来控制的,现在改成这种的也挺不错,并且有之外的收获
Demo:
public void FooRun()
{
Console.WriteLine("Create a new thread in ThreadPool:...");
// create cancellationTokenSource, which decide when to cancel(abort) thread
CancellationTokenSource cts = new CancellationTokenSource();
ThreadPool.QueueUserWorkItem(o => LoopFoo(cts.Token, 1000)); // delegate without parameter (WaitCall)
Thread.Sleep(180);
cts.Cancel();
Console.WriteLine("FooRun Done...");
}
public void LoopFoo(CancellationToken token, int countTo)
{
int i = 0;
while (i++ < countTo)
{
if (token.IsCancellationRequested)
{
Console.WriteLine("Is canceled...");
break;
}
// do something not care
Console.WriteLine(i);
Thread.Sleep(10);
}
Console.WriteLine("LoopFoo Done...");
}
可以看到,在望线程池丢一个Item的时候传了个 CancellationTokenSource 对象,它可以在线程的内部作为一个开关量使用,在主线程就可以在任意时间cancel掉它,然后让线程终止。
当然,如果只能这样,那就和static bool没有区别了,之所以我觉得有趣,是因为还活得了一个调用回调函数的机会
// create cancellationTokenSource, which decide when to cancel(abort) thread
CancellationTokenSource cts = new CancellationTokenSource();
cts.Token.Register(() => Console.WriteLine("CancellationToken register callback function invoked..."));
ThreadPool.QueueUserWorkItem(o => LoopFoo(cts.Token, 1000)); // delegate without parameter (WaitCall)
Thread.Sleep(180);
cts.Cancel();
可以注册多个Action<>,那就调用多个了。这点倒是很有意思,给你了更多的控制线程的方式。
还有一种link的方式创建TokenSource,这种方式使得如果关联的TokenSource,cancel了,那么将导致这个TokenSource也会cancel CancellationTokenSource one = new CancellationTokenSource();
one.Token.Register(() => Console.WriteLine("One register function invoked..."));
//create another new cancellationTokenSource
CancellationTokenSource two = new CancellationTokenSource();
two.Token.Register(() => Console.WriteLine("Two register function invoked..."));
//create a linked cancelationTokenSource
CancellationTokenSource three = CancellationTokenSource.CreateLinkedTokenSource(one.Token, two.Token);
three.Token.Register(() => Console.WriteLine("Three register function invoked..."));
Console.WriteLine("One's IsCancellationRequested: {0} \nTwo's IsCancellationRequested: {1} \nThree'sIsCancellationRequested: {2}",
one.IsCancellationRequested, two.IsCancellationRequested, three.IsCancellationRequested);
two.Cancel();
Console.WriteLine("One's IsCancellationRequested: {0} \nTwo's IsCancellationRequested: {1} \nThree'sIsCancellationRequested: {2}",
one.IsCancellationRequested, two.IsCancellationRequested, three.IsCancellationRequested);
one.Cancel();
Console.WriteLine("One's IsCancellationRequested: {0} \nTwo's IsCancellationRequested: {1} \nThree'sIsCancellationRequested: {2}",
one.IsCancellationRequested, two.IsCancellationRequested, three.IsCancellationRequested);
虽然暂时没有想到用在哪里,但是感觉还是很有用处的。
可以看到,CancellationToken 是真正起作用的关键点,CancellationTokenSource是对它的一个包装,在内部,定义了CancellationToken对象, 它是一个结构体,重载了!= ==操作符。如果想在最开始的Demo中不让线程由CancellationToken控制而退出,那可以在传参 CancellationToken.None