如何取消.net后台线程的执行

如题所述

如果后台线程将执行一个很长的计算,那么可以将计算隔成若干小段,并经常检查是否需要取消线程。.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();
}

private static void ThreadWork(object state)
{
CancellationToken cancellationToken = (CancellationToken)state;

while (true)
{
// 检查是否取消
if(cancellationToken.IsCancellationRequested)
{
Console.WriteLine("线程已经取消了");
Console.WriteLine("线程的资源已经清理完成。");
break;
}
// 模拟工作
Thread.SpinWait(500000);
Console.WriteLine("我还在工作。");
}
}
}

取消阻塞的线程
上面的示例中,后台线程会长时间进行计算,但更多的时候,线程会由于等待某个事件,从而进入阻塞状态。这个时候,实际上线程已经不再执行状态了,很明显,它没有机会去检查取消标志。 那么,该如何解决这个问题呢?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);

threadConsumer.Start(state);
threadProducter.Start(state);

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;
}
}
}
}
温馨提示:答案为网友推荐,仅供参考

相关了解……

你可能感兴趣的内容

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 非常风气网