正确终止线程的方法
在介绍正确方法前,我们先看下传统的停止方法:
thread.stop();
stop方法用来强行终止正在运行或挂起的线程。这个方法的危险之处在于:
如果线程当前正在执行的是一段非托管代码(为CLR而编写以及使用CLR服务的代码叫"托管代码",而那些未使用CLR服务的代码(也就是你多年以来一直编写的代码)叫"非托管代码"。),那么CLR就不会抛出ThreadAbortException,只有当代码继续回到CLR中时,才会引发ThreadAbortException。当然,即便是在CLR环境中,ThreadAbortException也不会立即引发。
正确方法:
1.使用退出标志终止线程
示例一
public static bool exit = false;
static void Main(string[] args)
{
Thread t = new Thread(PrintNumbers);
t.Start();
Thread.Sleep(6000);
exit = true;
}
static void PrintNumbers()
{
Console.WriteLine("Starting...");
for (int i = 1; i < 100; i++)
{
if (exit) break;
Thread.Sleep(TimeSpan.FromSeconds(2));
Console.WriteLine(i);
}
}</span>
示例二
public static bool exit = false;
static void Main(string[] args)
{
Thread t = new Thread(Run);
t.Start();
Thread.Sleep(6000);
exit = true;
}
static void Run()
{
while (!exit)
{
Thread.Sleep(TimeSpan.FromSeconds(2));
Console.WriteLine("Running...");
}
}
当PrintNumbers或Run方法执行完后,线程就会退出。但有时PrintNumbers方法是要很久而Run方法永远不会结束的。如果我们用for循环去处理一些大量数据,或用while在服务端程序中使用线程进行监听客户端请求,或是其他的需要循环处理的任务。在这种情况下,一般是将这些任务放在一个循环中,如for,while循环。但要想使for,while循环在某一特定条件下退出,最直接的方法就是设一个boolean类型的标志,并通过设置这个标志为true或false来控制for,while循环是否退出。
2.使用Interrupt方法终止线程
使用Interrupt方法来终端线程将抛出一个ThreadInterruptedException异常。
示例一static void Main(string[] args)
{
Thread t = new Thread(RunInterrupt);
t.Start();
Thread.Sleep(6000);
t.Interrupt();
}
static void RunInterrupt()
{
try
{
while (true)
{
Thread.Sleep(TimeSpan.FromSeconds(2));
Console.WriteLine("Running...");
}</span><span style="font-size:18px;">
}
catch (Exception)
{
Console.WriteLine("Stoped");
}
}
3.标准的取消模式:协作式取消(Cooperative Cancellation)
static CancellationTokenSource cts = new CancellationTokenSource();
static void Main(string[] args)
{
Console.WriteLine("按任意键终止线程!");
Thread t = new Thread(() =>
{
while (true)
{
if (cts.Token.IsCancellationRequested)
{
Console.WriteLine("线程被终止!");
break;
}
Console.WriteLine(DateTime.Now.ToString());
Thread.Sleep(1000);
}
});
t.Start();
Console.ReadKey();
cts.Cancel();
}
调用者使用 CancellationTokenSource的Cancle方法通知工作线程退出。工作线程则以大致1000毫秒的频率一边工作,一边检查是否有外界传入进来的Cancel信号。若有这样的信号,则负责退出。可以看到,在正确停止线程的机制中,真正起到主要作用的是线程本身。
协作式取消中的关键类型是CancellationTokenSource。它有一个关键属性 Token,Token是一个名为CancellationToken的值类型。CancellationToken继而进一步提供了布尔值的属性 IsCancellationRequested作为需要取消工作的标识。CancellationToken还有一个方法尤其值得注意,那就是 Register方法。它负责传递一个Action委托,在线程停止的时候被回调,使用方法如:
cts.Token.Register(() =>
{
Console.WriteLine("线程被终止了。");
});
以上就是正确终止线程的三种方法了,推荐使用第三种,最为标准。