Synchronize执行过程
Synchronize执行过程及原理
在windows原生应用程序开发中,经常伴随多线程的使用,多线程开发很简单,难点就是在于线程的同步,在Delphi中提供了VC中不具备的一个过程Synchronize,使用起来非常方便,解决了很多VC开发中碰到的常见问题,但是在看了很多Delphi代码后,发现很多人对于Synchronize的理解还是有问题的,不能很好地正确使用Synchronize过程,本文对Synchronize过程的使用提出一些个人的见解,供大家参考。
在VC中使用多线程,由于MFC或VC本身的特点,VC人员在更新窗口界面和工作线程的关系上分的是比较清楚的,但是Delphi里由于VCL提供的方便特性,造成大量人员在工作线程中更新窗口界面,给系统稳定带来潜在的危险,应该说比较严格的方法应该是永远让更新窗口界面的工作仅由主线程完成,工作线程仅仅做后台的一些工作,当工作线程的结果需要反馈到界面上来的时候,应该使用各种同步对象(临界区、互斥量)等来进行同步,然后让主线程更新窗口界面。
这里由于主要讲解Synchronize的使用,使用同步对象更新的方法就不说了,首先说一下在VC中比较接近Synchronize过程的SendMessage函数,其实在Delphi中也可以使用SendMessage来实现线程同步,实现通知主线程更新窗口界面,只是没有Synchronize过程用起来那么方便。
SendMessage函数的工作过程是比较复杂的,有兴趣的朋友可以多查查SendMessage函数及其同多线程的关系,如果在工作线程中调用SendMessage函数,工作线程会挂起,然后等待主线程空闲,主线程空闲开始处理接收到的消息,处理完成把结果返回,工作线程接收到返回结果后继续运行,也就是消息处理函数是在主线程中运行的,而且工作线程会挂起等待SendMessage函数返回即消息处理函数处理完成才会继续往下执行,在VC开发中这种方式也是经常被使用的。
理解了SendMessage函数工作过程,现在来说一下Synchronize过程的工作过程,Synchronize过程是Delphi底层实现的,其工作原理非常类似SendMessage函数,但是使用起来要比SendMessage函数方便易用,Synchronize过程开始时,也是会挂起当前的工作线程(使用的同步对象),然后让主线程执行Synchronize参数中具体的过程proc,工作线程等待proc执行,proc执行结束返回到工作线程,工作线程再继续执行。
总之,如果在TThread的Execute过程中仅仅调用一个Synchronize过程,Synchronize参数中的过程都是在主线程中执行的,等于没有使用多线程。也就是要细化Synchronize参数中的过程proc,仅让proc执行一些更新界面的工作,不能把真正耗时的动作放在proc中,不然使用多线程没有任何意义。
附:Delphi底层中Synchronize过程的实现过程简介
Synchronize过程的核心函数是System.Classes.pas中的过程class procedure TThread.Synchronize(ASyncRec: PSynchronizeRecord; QueueEvent: Boolean = False);这个函数中是通过调用WakeMainThread事件方法调用具体过程proc的,WakeMainThread事件的注册在Vcl.Forms.pas里,应用程序启动时由Application对象进行注册,WakeMainThread工作过程在Vcl.Forms.pas中为procedureTApplication.WakeMainThread(Sender: TObject);
begin
PostMessage(Handle, WM_NULL, 0, 0);
end;
也就是仅仅把WM_NULL消息放入应用程序消息队列中,工作线程调用完WakeMainThread事件方法即PostMessage以后就挂起(通过同步对象)等待proc执行完成信号触发,Vcl.Forms.pas中主线程消息处理函数中会看到如下代码
WM_NULL:
CheckSynchronize;
即在检索消息循环后碰到WM_NULL消息,会执行CheckSynchronize过程,CheckSynchronize过程在System.Classes.pas中function CheckSynchronize(Timeout: Integer= 0): Boolean; 其工作核心就是执行proc过程,并在执行完成后设置proc执行完成信号,工作线程检测到这个信号后会唤醒,并继续执行后续工作。以上过程中从Synchronize调用到PostMessage都是在工作线程中进行的,然后挂起,检索WM_NULL消息执行CheckSynchronize过程和proc过程都是在主线程中完成的,这些工作完成后,工作线程再唤醒继续执行。
以上来自网友http://blog.csdn.net/gogogo/article/details/10139501
个人调试总结:
1.工作线程调用Synchronize唤醒主线程(其实就是通过回调到主线程WakeMainThread接口,接口WakeMainThread再发消息WM_NULL);工作线程进入等待执行完成的信号;
2.主线程接收到WM_NULL消息后,再将进入CheckSynchronize,检查队列中需要执行的函数,当执行完成后,设置执行完成信号;工作线程等待结束,继续往下运行;
3.主线程接收到WM_NULL并不影响其他消息的进入,因为TApplication.Run接口中不停地轮寻消息,消息也会不停地进入各自的消息处理过程; 除非程序睡眠了
4.工作线程调用Synchronize参数列表中执行过程,不应该将耗时的业务交给主线程执行,耗时的业务应该交给工作线程执行
5.工作线程无法代替的工作,可以用Synchronize交给主线程执行;
Synchronize执行过程的更多相关文章
- ASP.NET Web API 过滤器创建、执行过程(二)
ASP.NET Web API 过滤器创建.执行过程(二) 前言 前面一篇中讲解了过滤器执行之前的创建,通过实现IFilterProvider注册到当前的HttpConfiguration里的服务容器 ...
- ASP.NET Web API 过滤器创建、执行过程(一)
ASP.NET Web API 过滤器创建.执行过程(一) 前言 在上一篇中我们讲到控制器的执行过程系列,这个系列要搁置一段时间了,因为在控制器执行的过程中包含的信息都是要单独的用一个系列来描述的,就 ...
- ASP.NET Web API 控制器执行过程(一)
ASP.NET Web API 控制器执行过程(一) 前言 前面两篇讲解了控制器的创建过程,只是从框架源码的角度去简单的了解,在控制器创建过后所执行的过程也是尤为重要的,本篇就来简单的说明一下控制器在 ...
- Struts2拦截器的执行过程浅析
在学习Struts2的过程中对拦截器和动作类的执行过程一度陷入误区,特别读了一下Struts2的源码,将自己的收获分享给正在困惑的童鞋... 开始先上图: 从Struts2的图可以看出当浏览器发出请求 ...
- 通过源码了解ASP.NET MVC 几种Filter的执行过程
一.前言 之前也阅读过MVC的源码,并了解过各个模块的运行原理和执行过程,但都没有形成文章(所以也忘得特别快),总感觉分析源码是大神的工作,而且很多人觉得平时根本不需要知道这些,会用就行了.其实阅读源 ...
- Hadoop MapReduce执行过程详解(带hadoop例子)
https://my.oschina.net/itblog/blog/275294 摘要: 本文通过一个例子,详细介绍Hadoop 的 MapReduce过程. 分析MapReduce执行过程 Map ...
- 高程(4):执行环境、作用域、上下文执行过程、垃圾收集、try...catch...
高程三 4.2.4.3 一.执行环境 1.全局执行环境是最外层的执行环境. 2.每个函数都有自己的执行环境,执行函数时,函数环境就会被推入一个当前环境栈中,执行完毕,栈将其环境弹出,把控制器返回给之前 ...
- saltstack命令执行过程
saltstack命令执行过程 具体步骤如下 Salt stack的Master与Minion之间通过ZeroMq进行消息传递,使用了ZeroMq的发布-订阅模式,连接方式包括tcp,ipc salt ...
- Web APi之过滤器执行过程原理解析【二】(十一)
前言 上一节我们详细讲解了过滤器的创建过程以及粗略的介绍了五种过滤器,用此五种过滤器对实现对执行Action方法各个时期的拦截非常重要.这一节我们简单将讲述在Action方法上.控制器上.全局上以及授 ...
随机推荐
- iOS 框架 Nimbus
Nimbus好像是用来处理 视图控制器的 解耦 参考: http://www.oschina.net/p/nimbuskit
- IM 融云 之 安装cocoapods 安装 SDK
1. podfile 内容如下: platform :ios, '7.0' pod 'RongCloudIMKitWithVoip', '2.4.3' 现在最新是2.4.3 导入之后,就直接可以用了. ...
- spring security 跨域防伪攻击
applicationContext-security.xml中配置 <http use-expressions="true" disable-url-rewriting=& ...
- centos command中 * . 的重要性
錯誤 cp /home/test1/* /home/test2/ –a 用參數*將不可以複製linux中.開頭的隱藏文件 正確 cp /home/test1/. home ...
- Java 页面的工具包
所谓工具包,是指把页面的功能划分出来,放到另外一个包里面.方面工程管理.结构清晰.团队协作等. 根据原来的例子:要做一个com.myweb包的工具包com.myweb.tool 为导航栏统一创建接口 ...
- LINQ to Sql系列二 简单查询和联接查询
这一篇文章主要总结LINQ to sql的简单查询(单表查询)和联接查询(多表查询) 单表查询 需求是我们要输出TClass表中的结果.使用了from-in-select语句,代码如下: public ...
- 简单加解密算法 - vb.net
Public Class Form1 Dim charAarray() As Char '加密 Private Sub Btn_En_Click(sender As System.O ...
- jmeter线程组配置
线程组配置 线程组相当于有多个用户,同时去执行相同的一批次任务.每个线程之间都是隔离的,互不影响的.一个线程的执行过程中,操作的变量,不会影响其他线程的变量值. Delay Thread creati ...
- HDU2553(回溯)
N皇后问题 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- KB奇遇记(10):终章
本来还想写一篇关于前CIO的著名言论,不过想想还是算了.博客空间宝贵,不乱恶心人了. 这篇博文是本系列<KB奇遇记>的最后一篇了. 虽然在KB公司有这么多的苦,但毕竟收获也很多,至少让我懂 ...