轮循方式 如果后台线程将执行一个很长的计算,那么可以将计算隔成若干小段,并经常检查是否需要取消线程。.NET框架提供了CancellationTokenSource类来作为线程取消的统一模式。例如: 复制代码 代码如下: public class Example { public static void Main() { CancellationTokenSource cts = new CancellationTokenSource(); var thread = new Thread(ThreadWork); thread.Start(cts.Token); while (true) { if(Console.ReadKey().KeyChar == 'c') { Console.WriteLine("请求取消线程的执行"); cts.Cancel(); break; } } Console.ReadLine(); }
取消阻塞的线程 上面的示例中,后台线程会长时间进行计算,但更多的时候,线程会由于等待某个事件,从而进入阻塞状态。这个时候,实际上线程已经不再执行状态了,很明显,它没有机会去检查取消标志。 那么,该如何解决这个问题呢?CancellationToken的WaitHandle属性提供了解答。WaitHandle类有一个静态方法WaitAny,它可以同时等待多个事件,当多个事件中的任意一个有效时,线程都会从阻塞状态中返回。可以根据WaitAny方法的返回值来判断发生了什么事件,从而相应的执行代码。例子: 复制代码 代码如下: public class Example { private static int Value;
public static void Main() { var autoResetEvent = new AutoResetEvent(false); var cts = new CancellationTokenSource(); var state = new { ValueAvailableEvent = autoResetEvent, CancellationToken = cts.Token }; var threadConsumer = new Thread(ConsumerThreadWork); var threadProducter = new Thread(ProducterThreadWork);
while (true) { if (Console.ReadKey().KeyChar == 'c') { Console.WriteLine("请求取消线程的执行"); cts.Cancel(); break; } } Console.ReadLine();
} public static void ProducterThreadWork(dynamic state) { var valueAvailableEvent = (AutoResetEvent)state.ValueAvailableEvent; var cancellationToken = (CancellationToken)state.CancellationToken; var rand = new Random(); while (!cancellationToken.IsCancellationRequested) { Value = rand.Next(); Console.WriteLine("\r\n产生一个值{0}", Value); valueAvailableEvent.Set(); Thread.Sleep(500); }
Console.WriteLine("生产者线程被取消。"); }
public static void ConsumerThreadWork(dynamic state) { var valueAvailableEvent = (AutoResetEvent)state.ValueAvailableEvent; var cancellationToken = (CancellationToken)state.CancellationToken; var events = new[] { valueAvailableEvent, cancellationToken.WaitHandle };
while (true) { var eventIndex = WaitHandle.WaitAny(events); // 处理数据 if (eventIndex == 0) { Console.WriteLine("处理值{0}。", Value); } // 处理取消事件 else if (eventIndex == 1) { Console.WriteLine("消费者线程被取消。"); break; } } } }