C#夯实基础之多线程二:主线程、前台线程与后台线程(转载)

摘要:
让我们从主线程、前台线程和后台线程开始:但是当接口线程关闭这10个线程时,下载任务后面的线程将自然关闭。当后台线程未完成时,后台线程也将停止。前台线程和后台线程之间的唯一区别是后台线程不会阻止进程终止。通过线程池创建的线程(稍后会提到)是后台线程。1.创建前台线程和后台线程staticvoidMain(string[]args){//当前主线程是前台线程,

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

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


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


       那么,问题来了,当我暂停这个下载任务时,后面10个线程会关掉,但界面线程关闭掉这10个线程的时候,我们并没有察觉,它们在后台悄默声地就关掉了。这10个线程就是我们说的后台线程
现在,我们把迅雷软件退出了,那么所有的下载任务都关掉了,下载任务背后的线程自然也会关掉,这个迅雷软件运行的线程就是我们说的主线程,它是一个前台线程
但当我们再在网页中重新找到可下载的内容时,迅雷的资源嗅探又可以检测到这些内容,交提示我们是否要下载。它不随着前面迅雷软件的退出而退出。


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


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


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

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



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

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

static void Main(string[] args)
{
    //当前主线程是个前台线程,且不能修改为后台线程
    Console.WriteLine(Thread.CurrentThread.IsBackground);

//Thread创建的线程是前台线程
Thread th = new Thread(delegate() { Console.WriteLine("start a new thread"); });
    Console.WriteLine(th.IsBackground);

    //Task使用程序池创建线程,默认为后台线程
    Task task = new Task(() => Console.WriteLine("start a new task"));

    Console.Read();
}

      输出结果:

C#夯实基础之多线程二:主线程、前台线程与后台线程(转载)第1张

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

static void Main(string[] args)
{
    //修改前台线程为后台线程
    Thread th = new Thread(delegate() { Console.WriteLine("start a new thread"); });
    Console.WriteLine(th.IsBackground);
    th.Start();
    th.IsBackground = true;
    Console.WriteLine(th.IsBackground);

    Console.Read();
}

      输出结果

C#夯实基础之多线程二:主线程、前台线程与后台线程(转载)第2张

      在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秒再执行输出

C#夯实基础之多线程二:主线程、前台线程与后台线程(转载)第3张

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

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

    });
    th.IsBackground = true;
    th.Start();

    Console.WriteLine("main thread end");
}

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

三.参考文档



      Thread.IsBackground

原文链接

免责声明:文章转载自《C#夯实基础之多线程二:主线程、前台线程与后台线程(转载)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇【游戏】《方舟生存进化》怎么联机 搭建服务器联机教程iOS如何实时查看App运行日志下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Thread.setDaemon设置说明

转载地址:http://blog.csdn.net/m13666368773/article/details/7245570 Thread.setDaemon的用法,经过学习以后了解: 1. setDaemon需要在start方法调用之前使用 2. 线程划分为用户线程和后台(daemon)进程,setDaemon将线程设置为后台进程 3....

利用C#线程窗口调试多线程程序

       从网上的资料判断,调试多线程程序似乎就一下3种方法。 1、在日志的某个地方写日志文件。 优点:不会干扰程序的执行,特别是对网络的多线程通信。 缺点:每次都需要打开日志文件以查看进程运行的信息。 2、利用断点进行调试。 优点:直观,可以直接看到运行过程的值 缺点:在多个线程设置断点,可能让程序跳来跳去,还需要额外地分出一部分精力用来理清程序...

python--GIL锁

GIL锁 本节目录 一 介绍 二 GIL介绍 三 GIL与Lock 四 GIL与多线程 五 多线程性能测试 一 背景知识 ''' 定义: In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads fr...

条件变量用例--解锁与signal的顺序问题

         我们知道,当调用signal/broadcast唤醒等待条件变量的其他线程时,既可以在加锁的情况下调用signal/broadcast,也可以在解锁的情况下调用。          那么,到底哪种情况更好呢?man手册中其实已经给出了答案:          The pthread_cond_broadcast() or pthread_...

java面试宝典

相关概念 面向对象的三个特征 封装,继承,多态.这个应该是人人皆知.有时候也会加上抽象. 多态的好处 允许不同类对象对同一消息做出响应,即同一消息可以根据发送对象的不同而采用多种不同的行为方式(发送消息就是函数调用).主要有以下优点: 可替换性:多态对已存在代码具有可替换性. 可扩充性:增加新的子类不影响已经存在的类结构. 接口性:多态是超累通过方法签名...

Qt 学习之路 2(75):线程总结

前面我们已经详细介绍过有关线程的一些值得注意的事项。现在我们开始对线程做一些总结。 有关线程,你可以做的是: 在QThread子类添加信号。这是绝对安全的,并且也是正确的(前面我们已经详细介绍过,发送者的线程依附性没有关系) 不应该做的是: 调用moveToThread(this)函数 指定连接类型:这通常意味着你正在做错误的事情,比如将QThread控...