UI线程与worker线程
也谈谈我对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线程的更多相关文章
- 模板应用--UI线程与worker线程同步 模仿c# invoke
由之前的一篇博文 <UI线程与worker线程><UI线程与worker线程>引出,UI线程与worker线程“串行化”在win32上实现是多么没有节操的事情,代码编写麻烦不说 ...
- 在netty3.x中存在两种线程:boss线程和worker线程。
在netty 3.x 中存在两种线程:boss线程和worker线程.
- Android 实战之UI线程和Worker线程交互
哈哈,博文取了个比较霸气的名字,大家不都喜欢这样忽悠人吗 呵呵! 好了,现在就是很简单的点击查询,然后这个查询有点花时间,不想见面出现假死现象,所以在另外的线程进行查询. 好了,代码在此: packa ...
- HTML5_06之拖放API、Worker线程、Storage存储
1.拖放API中源对象与目标对象事件间的数据传递: ①创建全局变量--污染全局对象: var 全局变量=null; src.ondragstart=function(){ 全局变量=数据值; ...
- UI线程和工作者线程
本文转载于:http://blog.csdn.net/libaineu2004/article/details/40398405 1.线程分为UI线程和工作者线程,UI线程有窗口,窗口自建了消息队列, ...
- 为什么说android UI操作不是线程安全的
转载于:http://blog.csdn.net/lvxiangan/article/details/17218409#t2 UI线程及Android的单线程模型原则 使用Worker线程 Commu ...
- 【转】 Pro Android学习笔记(九十):了解Handler(4):Worker线程
目录(?)[-] worker线程小例子 小例子代码worker线程通过handler实现与主线程的通信 小例子代码继承Handler代码 小例子代码子线程的Runnable 文章转载只能用于非商业性 ...
- C# 多线程详解 Part.02(UI 线程和子线程的互动、ProgressBar 的异步调用)
我们先来看一段运行时会抛出 InvalidOperationException 异常的代码段: private void btnThreadA_Click(object sender, ...
- Android的UI设计与后台线程交互
本文将讨论Android应用程序的线程模型以及如何使用线程来处理耗时较长的操作,而不是在主线程中执行,保证用户界面(UI)的流畅运行.本文还将阐述一些用户界面(UI)中与线程交互的API.UI用户界面 ...
随机推荐
- system.exit(0) vs system.exit(1)
2.解析 查看java.lang.System的源代码,我们可以找到System.exit(status)这个方法的说明,代码如下: /** * Terminates the currently ru ...
- PM产品经理练级攻略(1-5等级)
大家都叫“PM”,但做的事情却完全不同? “PM”这个词到底是什么意思? 这个话题恐怕也是各位同行都一直在想,也一直想不清楚的吧,我也是. 每次看到各种“产品经理的能力模型”,我都觉得有点扯淡,总觉得 ...
- GO学习资源站
GO语言学习资源网站 http://golangtc.com https://gobyexample.com http://golang-examples.tumblr.com
- Linux进程间通信——使用命名管道
在前一篇文章——Linux进程间通信——使用匿名管道中,我们看到了如何使用匿名管道来在进程之间传递数据,同时也看到了这个方式的一个缺陷,就是这些进程都由一个共同的祖先进程启动,这给我们在不相关的的进程 ...
- c++优先级
蒟蒻连c++的运算优先级都搞不清楚QAQ 转载自http://www.cnblogs.com/chenglei/archive/2009/08/03/1537822.html C++优先级列表 Pre ...
- EasyUI两种动态添加tab Iframe页面的方法
/** 动态添加tab-----方式一 **/ function addIframeTab(titleTxt,href,icon) { $('#mytabs').tabs('addIframeTab' ...
- 模板应用--UI线程与worker线程同步 模仿c# invoke
由之前的一篇博文 <UI线程与worker线程><UI线程与worker线程>引出,UI线程与worker线程“串行化”在win32上实现是多么没有节操的事情,代码编写麻烦不说 ...
- [Linux] rlwrap - 解决Linux下sqlplus退格、上翻键乱码问题
在Linux下使用sqlplus你会发现:退格键无法正常使用(乱码),上翻键也无法正常显示历史功能,非常讨厌! 为了让退格键和上翻键在sqlplus里正常发挥它的作用,我们必须安装一个软件 - rlw ...
- javascript之函数节流
对于高频率的事件触发,为了优化页面性能,我们一般会对其做函数节流.比如: resize.keydow.scroll事件等.用户的频繁操作,会导致事件高频率的执行,这样会出现页面抖动啊.频繁调接口啊等问 ...
- PHP上传图片至阿里云
<?php header("Content-type: text/html; charset=utf-8"); header('Access-Control-Allow-Or ...