在CLR中线程有前台线程和后台线程之分,一个进程的所有前台线程停止运行时,CLR强制终止所有仍在运行的后台线程,且后台线程不会抛出异常。
在线程的生存周期,任何时候都可以从前台线程变成后台线程或者从后台线程变成前台线程。通过代码构造一个Thread对象显示的创建线程都是前台线程,通过线程池ThreadPool/Task创建的线程都是后台线程。
通过下面的代码可以感受下前台线程后台线程的区别。
static void Main(string[] args)
{
//Thread 构造默认创建前台线程
Thread thread = new Thread(Worker);
//将线程变为后台线程
thread.IsBackground = true;
//启动线程
thread.Start();
//如果thread是前台线程,则应用程序10s后终止
//如果thread是后台线程,则应用线程立即终止
Console.WriteLine("Returning from main");
}
static void Worker()
{
//模拟10s的耗时操作
Thread.Sleep(10000);
//下面这行代码总会有在前一个前台线程被执行时才会显示
Console.WriteLine("Returning from worker");
}
需要注意的是,在开放过程中应该尽量避免使用前台线程,除非是明确需要的情况下,因为使用前台线程会阻止应用程序的退出。当应用程序的所有界面全部关闭,但仍有前台线程运行时,会导致应用程序的进程无法完全退出。
在开发过程中开辟线程时更推荐使用Task,使用的优先级应当是Task>ThreadPool>Thread
Task 其实也是一种线程池,相比于其余两种更依赖于CPU,在多核CPU上有更为良好的性能,同时提供了更丰富的API用于管理和追踪线程的执行状态。