前台线程和后台线程的问题

线程按照结束方式来说,分为前台线程和后台线程

一个应用程序运行,会启动一个进程,这个进程拥有多个线程,其中可能有前台线程,也有后台线程。只有所有的前台线程都结束了,系统才会卸载应用程序域,也就是说,停止该进程,回收该进程占用的内存等资源。后台线程必须依附于某个前台线程,不能单独存在。当所有的前台线程都退出后,系统会强制结束所有的后台线程,并卸载应用程序域。举个例子来说,有一个WinForm程序,第一种情况,A为UI线程,是前台线程,B也为前台线程,向某一个文本写入信息。注意,B线程是不像UI线程那样能够直观的让人看见,有点类似于QQ等后台运行的意思,但是这依然是一个前台线程。这是由线程的IsBackgournd属性决定的。B线程自打开始运行后,就不会再受到父线程的任何影响,两者是一个完全平行的关系。当我们关闭UI后,前台线程结束了,虽然现在看不到任何界面,但是子线程B线程依然在运行。所以,系统也就没有结束这些线程所在的进程。第二种情况,A为UI线程,是前台线程,B为向文本写入内容的线程,但这次设置为了后台线程。当我们把UI线程关闭后,所有的前台线程都消失了,此时,B线程的父线程结束了,B线程也会被系统强制结束。我们发现,向文本写入内容的后台线程已经自动被强制结束了。


主线程与子线程,是线程出现方式上的概念

一个线程产生了另一个线程,前者就是主线程,后者就是子线程。线程一旦产生,那么就与主线程是平等的地位,没有主次的关系。在WinForm程序中,第一个线程是UI线程,其他线程都是由这个线程产生的,所以UI线程是主线程。但是从这个线程衍生出来的任何线程,无论是前台线程,还是后台线程,相互之间,以及与UI线程,都是地位平等的关系。如果产生的子线程是前台线程,那么主线程与子线程就是在生命周期方面是平行的关系,相互之间是平等的。如果产生的子线程是后台线程,那么,这个线程与前台线程唯一的区别就是,不会阻止进程的结束,当所有前台线程结束后,这个线程会被强制结束

这样设计的原因:因为后台线程一般做的都是需要花费大量时间的工作,如果不这样设计,主线程已经结束,而后台工作线程还在继续,后台线程即时执行完成也已经没有什么实际的意义。比如说,有一个WinForm程序,UI用来显示计算结果,子线程B用来进行大量的十分耗时耗资源的计算。当用户打开程序后,由于某种原因,UI线程死掉并且退出了,如果此时子线程不是后台线程被强制结束的话,剩下的耗时耗资源的运算是没有意义的,因为即使有了结果,也无法再UI上来显示,因为UI已经退出了。另外的例子,Word的UI线程为前台线程,拼写检查为后台线程。如果关闭Word应用程序,拼写检查器继续运行器进程就没有意义了。在应用程序结束时,拼写检查器就可以关闭了。


主线程与子线程,前台线程与后台线程,是从线程的生成顺序和线程是否阻止进程退出这两个不同的方面进行区分的,是不同方面的概念。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C#中前台线程后台线程的举例: 1. 前台线程举例: ```csharp using System; using System.Threading; class Program { static void Main(string[] args) { Thread t = new Thread(new ThreadStart(CountNumbers)); t.Start(); for (int i = 1; i <= 5; i++) { Console.WriteLine("Main thread: " + i); Thread.Sleep(1000); } } static void CountNumbers() { for (int i = 1; i <= 5; i++) { Console.WriteLine("Child thread: " + i); Thread.Sleep(1000); } } } ``` 在这个例子中,我们创建了一个新的线程t,并在该线程上执行CountNumbers方法。在主线程中,我们打印了5个数字,并在每个数字之间暂停了1秒钟。在CountNumbers方法中,我们也打印了5个数字,并在每个数字之间暂停了1秒钟。由于我们在前台线程上执行CountNumbers方法,因此在主线程和子线程之间会交替打印数字。 2. 后台线程举例: ```csharp using System; using System.Threading; class Program { static void Main(string[] args) { Thread t = new Thread(new ThreadStart(CountNumbers)); t.IsBackground = true; t.Start(); for (int i = 1; i <= 5; i++) { Console.WriteLine("Main thread: " + i); Thread.Sleep(1000); } } static void CountNumbers() { for (int i = 1; i <= 10; i++) { Console.WriteLine("Child thread: " + i); Thread.Sleep(1000); } } } ``` 在这个例子中,我们创建了一个新的线程t,并在该线程上执行CountNumbers方法。我们将线程t设置为后台线程,这意味着当主线程退出时,线程t也会被强制终止。在主线程中,我们打印了5个数字,并在每个数字之间暂停了1秒钟。在CountNumbers方法中,我们打印了10个数字,并在每个数字之间暂停了1秒钟。由于我们在后台线程上执行CountNumbers方法,因此当主线程退出时,线程t也会被强制终止,因此只有前5个数字被打印出来。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值