• C#夯实基础之多线程二:主线程、前台线程与后台线程


          我们在C#夯实基础之多线程一:初识多线程》一文中第二部分中指出,既然windows最终发展出了多线程模型,按理说,我们直接使用一个.NetFramework的线程类就可以直接撸代码了,但在这之前,我们还需要认识一下线程的一些基本特性,它们的出现并不是多余的,而是为了解决一部分问题出现的,毕竟存在即合理,我们先说主线程、前台线程和后台线程:

    一.主线程、前台线程与后台线程

       相信前几年,大家都用过迅雷,用来下载文件是非常方便的,更重要的是速度快。那么,它的速度非常之快,全速下载的时候明显地拉慢了整个系统的响应时间,说明他占用了大量的系统资源。那它为什么这么快?知乎上的yskin用户解释说一个下载任务进来,迅雷把文件平分成10份,然后开10个线程分别下载。这时主界面是一个单独的线程,并不会因为下载文件而卡死。而且主线程可以控制下属线程,比如某个线程下载缓慢甚至停止,主线程可以把它强行关掉并重启另外一个线程。 这么多线程同时工作,正常情况下,下载速度会有质的提升。 

       那么,问题来了,当我暂停这个下载任务时,后面10个线程会关掉,但界面线程关闭掉这10个线程的时候,我们并没有察觉,它们在后台悄默声地就关掉了。这10个线程就是我们说的后台线程 

    现在,我们把迅雷软件退出了,那么所有的下载任务都关掉了,下载任务背后的线程自然也会关掉,这个迅雷软件运行的线程就是我们说的主线程,它是一个前台线程 

    但当我们再在网页中重新找到可下载的内容时,迅雷的资源嗅探又可以检测到这些内容,交提示我们是否要下载。它不随着前面迅雷软件的退出而退出。 

       如果你觉得这个例子不好理解,《C#高级编程》中也有一个,当你使用word来编辑文档时,它会实时提供一些拼写检查,当你需要打印文档时,可以选择后台打印,在打印机打印文档的同时,你可以继续编辑当前文档。同时word文档关闭时,这个打印任务可继续执行,直到打印出来,但拼写检查任务不会再执行。 

    这就是主线程、前台线程与后台线程的一些类比。下面,我们来说结论。 

       当一个程序启动时,就有一个进程被操作系统(OS)创建,与此同时一个线程也立刻运行,该线程通常叫做程序的主线程Main Thread),因为它是程序开始时就执行的,如果你需要再创建线程,那么创建的线程就是这个主线程的子线程,它是前台线程。 

       新建的子线程可以是前台线程或者后台线程,前台线程必须全部执行完,即使主线程关闭掉,这时进程仍然存活。后台线程在未执行完成时,如果前台线程关掉,则后台线程也会停掉,且不抛出异常。也就是说,前台线程与后台线程唯一的区别是后台线程不会阻止进程终止。可以在任何时候将前台线程修改为后台线程。

    二.C#中的前台线程与后台线程

       C#中,Thread类默认创建的是前台线程,通过线程池(后面会讲到)创建的线程都是后台线程。

           1.创建前台线程和后台线程

     1 static void Main(string[] args)
     2 {
     3     //当前主线程是个前台线程,且不能修改为后台线程
     4     Console.WriteLine(Thread.CurrentThread.IsBackground);
     5 
     6 //Thread创建的线程是前台线程
     7 Thread th = new Thread(delegate() { Console.WriteLine("start a new thread"); });
     8     Console.WriteLine(th.IsBackground);
     9 
    10     //Task使用程序池创建线程,默认为后台线程
    11     Task task = new Task(() => Console.WriteLine("start a new task"));
    12 
    13     Console.Read();
    14 }

           输出结果:

       

          2.修改前台线程为后台线程

     1 static void Main(string[] args)
     2 {
     3     //修改前台线程为后台线程
     4     Thread th = new Thread(delegate() { Console.WriteLine("start a new thread"); });
     5     Console.WriteLine(th.IsBackground);
     6     th.Start();
     7     th.IsBackground = true;
     8     Console.WriteLine(th.IsBackground);
     9 
    10     Console.Read();
    11 }

         输出结果

         

         C#中,前台线程可以修改为后台线程,这是由HostProtectionAttribute属性的SelfAffectingThreading字段决定的,如果可以变成后台线程,则值为true.

        3.前台线程阻止进程的关闭

    static void Main(string[] args)
     {
         //前台线程阻止了主线程的关闭
         Thread th = new Thread(delegate()
         {
             Thread.Sleep(6000);
             Console.WriteLine("start a new thread");
    
         });
         th.Start();
    
         Console.WriteLine("main thread end");
     }

         输出结果:这里主线程马上执行完成,并不马上关闭,前台线程等待6秒再执行输出

         

         4.后台线程不阻止进程的关闭

     1 static void Main(string[] args)
     2 {
     3     //后台线程不阻止主线程的关闭
     4     Thread th = new Thread(delegate()
     5     {
     6         Thread.Sleep(6000);
     7         Console.WriteLine("start a new thread");
     8 
     9     });
    10     th.IsBackground = true;
    11     th.Start();
    12 
    13     Console.WriteLine("main thread end");
    14 }

        结果:不等线程执行完成,主线程执行完毕后自动退出。

    三.参考文档

       http://technet.microsoft.com/zh-cn/library/system.threading.thread.isbackground

  • 相关阅读:
    JavaScript学习——使用JS实现首页轮播图效果
    JavaScript学习——使用JS完成注册页面表单校验
    JavaScript基础
    HTML&CSS——使用DIV和CSS完成网站首页重构
    HTML&CSS——网站注册页面
    java ------------ 集合(四) Collections类
    Java ---------- 集合(三) Map接口
    java ---------- 集合(二) Set 接口和Iterator 接口
    Java ---------- 集合
    idea -------- 常用快捷键
  • 原文地址:https://www.cnblogs.com/gudi/p/6233977.html
Copyright © 2020-2023  润新知