也谈谈我对UI线程和worker线程的理解

UI线程又叫界面线程,能够响应操作系统的特定消息,包括界面消息、鼠标键盘消息、自定义消息等,是在普通的worker线程基础上加上消息循环来实现的,在这个消息循环上不断地获取操作系统或其他线程派发过来的消息(就是个线程里面执行for循环的主),再根据这个消息找到对应的消息处理对象/函数,如果暂时没有消息需要处理就让线程等待,让出CPU时间片,以此表现出该线程一直“在线”的状态,直到某一特定退出消息结束线程。

worker线程又叫工作者线程,为了不影响UI线程的长时间任务处理导致的界面操作阻塞,提升用户体验,开以考虑开辟一个worker线程来完成复杂的任务,任务处理完后可以让它立即退出也可以让它继续等待新的任务,看具体需要。一个处理完任务后不退出而处于等待状态的worker线程其实跟UI线程已经没多大区别了,在worker线程也可以自己实现一个任务队列,然后不断地获取任务来达到UI线程的效果。

不管在什么操作系统,UI线程与worker线程协同工作不可避免地都会面对线程同步执行的问题,这里同步执行不是“对象状态同步”的概念,而是将线程执行“串行化”,比如线程A要执行后续的代码段之前先要等待线程B完成某一特定任务,当然,也可以通过“对象状态同步”的方式来达到这个效果,只是会比较麻烦一点。

以windows系统为例,当worker线程处理完结果后,需要把结果返回给UI线程,好让界面能够更新显示最新的状态,有这么几种方式:

    1.直接在worker线程执行处调用API::SendMessage,把消息和附带参数发往UI线程的消息队列,让UI线程从挂起状态恢复成执行态后从消息泵获取处理,如果当前消息泵没有其他消息,则立即处理此消息,否则需等待其他消息处理完后轮到它才执行,而此时worker线程处于等待消息处理的状态,UI线程处理完消息后,它才继续往下执行;

    2.直接在worker线程执行处调用API::PostMessage,与SendMessage一样,只不过,这是worker线程不等待处理结果,继续往下走,又叫异步方式。如果PostMessage有附带参数,这时就得谨慎处理了,就像普通的线程异步处理一样,对象必须加锁解锁,除非这个附带参数是临时从堆上分配的对象,由UI线程处理完消息前负责释放,但是这又涉及到模块之间的内存申请、释放问题,搞不好,程序直接core dump。

    3.worker线程直接把结果存放于UI线程能访问的某一处,等到UI线程执行到需要用到该结果时才访问,也要对这个对象进行加锁解锁,搞不好容易死锁。

以上3中方法,不管是哪种,处理起来都很麻烦,尽管第一种方式相对比较简单,可是写起代码来还是觉得繁琐,要先定义一个双方认识的消息(还得考虑该消息会不会冲突,是否考虑使用RegisterWindowMessage),定义好消息处理函数,然后添加消息映射宏,而且代码看起来不如顺序执行那么流畅,维护代码时要在这些地方跳来跳去,且还不论有多种同步消息需要同步,时间久了,只会越来越难维护。

接触这种线程“伪同步”一段时间后,自然而然对这种方式反感,开始思考一个问题:为什么操作系统不提供一个线程切换的API供调用,这样多省事啊。等待认真了解线程工作原理后,才发现这想法太天真了。

通常一个线程得以被操作系统调度运行,是因为符合当前优先级配置,且该线程尚有代码需要执行(这样说貌似也不太合理,想不出来),最直观的就是函数调用(不管全局函数也好、构造函数也好。。。),既然是函数调用那肯定有参数、变量入栈出栈,每个线程被挂起后,为了恢复执行后能够之前的状态下继续执行,就必然是一个线程对应一个线程栈,以此线程间互不干扰,各自在自己的一亩三分地上干活。这时再考虑线程“串行化”的问题,如果系统要提供线程切换的API,那么worker线程需要与UI线程同步时就必须让UI线程切换到worker线程拥有的线程栈上来,否则如何访问worker线程中的那些变量、参数,UI线程切换过来后,之前保留的现场又该怎么处理,如果栈是可拷贝的,那UI线程把它拷贝过来后置于栈顶,那栈可用空间不够大怎么办。此外还有种种我这水平未能触及的原因,发现真要这么做的话,这代价实在太高了,还不能保证如预期那样进行。

UI线程与worker线程的更多相关文章

  1. 模板应用--UI线程与worker线程同步 模仿c# invoke

    由之前的一篇博文 <UI线程与worker线程><UI线程与worker线程>引出,UI线程与worker线程“串行化”在win32上实现是多么没有节操的事情,代码编写麻烦不说 ...

  2. 在netty3.x中存在两种线程:boss线程和worker线程。

    在netty 3.x 中存在两种线程:boss线程和worker线程.

  3. Android 实战之UI线程和Worker线程交互

    哈哈,博文取了个比较霸气的名字,大家不都喜欢这样忽悠人吗 呵呵! 好了,现在就是很简单的点击查询,然后这个查询有点花时间,不想见面出现假死现象,所以在另外的线程进行查询. 好了,代码在此: packa ...

  4. HTML5_06之拖放API、Worker线程、Storage存储

    1.拖放API中源对象与目标对象事件间的数据传递: ①创建全局变量--污染全局对象:  var 全局变量=null;  src.ondragstart=function(){   全局变量=数据值;  ...

  5. UI线程和工作者线程

    本文转载于:http://blog.csdn.net/libaineu2004/article/details/40398405 1.线程分为UI线程和工作者线程,UI线程有窗口,窗口自建了消息队列, ...

  6. 为什么说android UI操作不是线程安全的

    转载于:http://blog.csdn.net/lvxiangan/article/details/17218409#t2 UI线程及Android的单线程模型原则 使用Worker线程 Commu ...

  7. 【转】 Pro Android学习笔记(九十):了解Handler(4):Worker线程

    目录(?)[-] worker线程小例子 小例子代码worker线程通过handler实现与主线程的通信 小例子代码继承Handler代码 小例子代码子线程的Runnable 文章转载只能用于非商业性 ...

  8. C# 多线程详解 Part.02(UI 线程和子线程的互动、ProgressBar 的异步调用)

           我们先来看一段运行时会抛出 InvalidOperationException 异常的代码段: private void btnThreadA_Click(object sender, ...

  9. Android的UI设计与后台线程交互

    本文将讨论Android应用程序的线程模型以及如何使用线程来处理耗时较长的操作,而不是在主线程中执行,保证用户界面(UI)的流畅运行.本文还将阐述一些用户界面(UI)中与线程交互的API.UI用户界面 ...

随机推荐

  1. Oracle EBS-SQL (CST-2):检查有BOM但成本不基于累积的数据.sql

    select c.segment1                                                                          物料编码,     ...

  2. QTDesigner的QVBoxLayout自动随窗口拉伸

    在MainWindow的构造函数中添加如下代码://设置Uiui.setupUi(this); //使Ui可自适应父窗口大小QVBoxLayout* mainLayout = new QVBoxLay ...

  3. nodejs面试

    1. PM2相关 1. PM2的主要功能?*答案:在Node.js进程挂掉以后自动重启进程,并且能够方便的实现Node.js的集群模式* 2. 如何查看当前是否适合重启服务?*答案:pm2 monit ...

  4. CoreData多表操作.

    这次给大家带来的是CoreData多表操作的使用. 首先我们要对CoreData来进行多表操作我们先要创建至少两个实体在工程中. 在创建完成这两个对应的工程实体文件和工程中的类文件后我们现在需要创建一 ...

  5. 开源 iOS 项目分类索引大全

    GitHub 上大概600个开源 iOS 项目的分类和介绍,对于你挑选和使用开源项目应该有帮助 系统基础库 Category/Util sstoolkit 一套Category类型的库,附带很多自定义 ...

  6. 网页前台的iframe控制内部刷新子页

    <body> <!--Header--> <uc1:top runat="server" ID="top" /> <! ...

  7. DEDE列表页调用TAG标签

    [field:id function=GetTags(@me)/] 标签就可以调用出来了 只不过不带连接的,如果需要连接,请注释include\helpers\archive.helper.php文件 ...

  8. STM32F407VG (三)ADC

    12位ADC是一种逐次逼近型模拟数字转换器. 它有多达19个通道,可測量16个外部和2个内部信号源和VBAT通道.各通道的A/D转换能够单次.连续.扫描或间断模式运行. ADC的结果能够左对齐或右对齐 ...

  9. 集装箱学习(两):动手模拟AOP

    简单的说,Spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器框架. 上文已经介绍模拟IoC实现,这篇文章来动手模拟AOP. AOP简述 面向对象强调"一切皆是对象&quo ...

  10. 【递归】【3月周赛1】【Problem B】

    Problem B Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other) Total Sub ...