由于Delphi的VCL非常方便,导致开发人员不像在VC下更新窗口界面和工作线程的关系上分的那么清楚,给系统稳定带来潜在的危险。最好的方法是永远让更新窗口界面的工作仅由主线程完成,工作线程仅仅做后台的一些工作,当工作线程的结果需要反馈到界面上来的时候,应该使用各种同步对象(临界区、互斥量)等来进行同步,然后让主线程更新窗口界面。如果通过API建立线程,可以采用SendMessage来实现线程同步,实现通知主线程更新窗口界面,只是这往往是比较复杂的,Delphi提供了一个非常方便的方法,使用Synchronize过程。
如果在工作线程中调用SendMessage函数,工作线程会挂起,然后等待主线程空闲,主线程空闲开始处理接收到的消息,处理完成把结果返回,工作线程接收到返回结果后继续运行,也就是消息处理函数是在主线程中运行的,而且工作线程会挂起等待SendMessage函数返回即消息处理函数处理完成才会继续往下执行,在VC开发中这种方式也是经常被使用的。
Synchronize过程是Delphi底层实现的,其工作原理非常类似SendMessage函数,但是使用起来要比SendMessage函数方便易用,Synchronize过程开始时,也是会挂起当前的工作线程(使用的同步对象),然后让主线程执行Synchronize参数中具体的过程proc,工作线程等待proc执行,proc执行结束返回到工作线程,工作线程再继续执行。
如果在TThread的Execute过程中仅仅调用一个Synchronize过程,Synchronize参数中的过程都是在主线程中执行的,等于没有使用多线程。也就是要细化Synchronize参数中的过程proc,仅让proc执行一些更新界面的工作,不能把真正耗时的动作放在proc中,不然使用多线程没有任何意义。
从以上Synchronize原理可以看出,Synchronize里的过程是由主线程执行的,所以可以这么应用:Synchronize参数里面的代码就是多线程需要公共的代码,使同一时间只有一个线程使用那部分资源。最后要说明两点:
Synchronize调用的过程,必须是无参数过程。
线程是通过线程类TThread建立的才可以使用Synchronize。
具体示例请参考: http://evelee.net/blog/?id=24