VCL线程的同步方法 Synchronize(用消息来同步)

看本文时,能够同时参考:Delphi中线程类 TThread实现多线程编程(事件、临界区、Synchronize、WaitFor……)html

 

先说一下RTL和VCL数据库

  RTL(Run-Time library),运行时库,包括System、SysUtils、Math三个单元,提供的函数与语言、编译器、操做系统及进程有关编程

  RTL提供类之间继承于 TObject 和 RTL内部的类安全

  VCL(Visual Component Library),可视化组件库,包括Graphics、classes、Controls等与类和组件相关的单元多线程

 

VCL不是线程安全的ide

   由于VCL不是线程安全的,因此对VCL的访问只能在主线程中。这将意味着:全部须要与用户打交道的代码都只能在主线程的环境中执行。这是其结构上明显的不足,而且这种需求看起来只局限在表面上,但它实际上有一些优势函数

  开发多线程项目的主要须要考虑的一点就是同步多线程使用资源,不要产生冲突,其实想Delphi的VCL组件也是一种资源,可是VCL不是线程安全的,不能让其余的线程使用,只能经过主线程来使用它性能

 

1.可能的一个应用场景spa

  好比在开发图形化界面的项目中,须要链接数据库,能够采用这样的策略:用主线程来绘制组件到图形化界面,而链接数据库的过程在子线程中实现。操作系统

  这时候可以保证就算在链接数据库的时候出现问题,子线程可能会去尝试一直链接,可是由于各个线程之间互不相干,各自执行各自的逻辑代码,因此不影响主线程绘制组件,因此窗体并不会卡住

  可是可能要在子线程中读取数据库中的数据来展现数据,这个时候,由于VCL 不是线程安全的,因此不能容许主线程(绘制组件)和子线程(想要去将从数据库中的数据“写”到界面上)同时去操做组件

  因此可能的解决方法(见 3.Synchronize() 方法)就是 使用Synchronize() 方法来调用子线程想要将数据“写到”界面的方法,这样就能保证这个方法其实是在主线程中执行的(虽然它是子线程的方法,可是经过Synchronize() 方法能够实现将子线程的方法放到主线程中执行),这样就能保证不会出现多个线程使用VCL 组件

 

2.单线程用户界面的好处

  首先,只有一个线程可以访问用户界面,这减小了编程的复杂性。Win32 要求每一个建立窗口的线程都要使用 GetMessage() 创建本身的消息循环。正如你所想的,这样的程序将会很是难于调试,由于消息的来源实在太多了

  其次,因为 VCL只用一个线程来访问它,那些用于把线程同步的代码就能够省略了,从而改善了应用程序的性能

 

3.Synchronize() 方法

  在 TThread中有一个方法叫Synchronize(),经过它可让子线程的一些方法在主线程中执行。Synchronize() 的声明以下

1
procedure  Synchronize(Method: TThreadMethod);

  参数Method 的类型是 TThreadMethod(这是一个无参数的过程),类型的声明以下

1
2
type
     TThreadMethod =  procedure  of  object ;

  Method参数用来传递在主线程中执行的方法。以 TTestThread对象为例,若是要在一个编辑框中显示计算的结果。首先要在TTestThread中增长能对编辑控件的Text 属性进行修改的方法,而后,用Synchronize() 来调用此方法

  给这个方法取名 GiveAnswer(),下面列出例子的代码,其中包含了更新主窗体的编辑控件的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
unit  ThrdU;
 
interface
uses
     Classes;
 
type
     TTestThread =  class (TThread)
     private
         Answer:  Integer ;
     protected
         procedure  GiveAnswer;
         procedure  Execute; override;
     end ;
 
implementation
uses
     SysUtils, Main;
 
{TTestThread}
procedure  TTestThread . GiveAnswer;
begin
     MainForm . Edit1 . Text := IntToStr(Answer);
end ;
 
procedure  TTestThread . Execute;
var
     I:  Integer ;
begin
     FreeOnTerminate:=  True ;
     for  I:=  1  to  2000000  do
     begin
         if  Terminated  then  Breadk;
         Inc(Answer, Round( Abs (Sin(Sqrt(I))));
         Synchronize(GiveAnswer);
     end ;
end ;

  Synchronize() 的做用是在主线程中执行一个方法。

  当你在程序中第一次建立一个附属线程时,VCL 将会从主线程环境中建立和维护一个隐含的线程窗口。此窗口惟一的目的是把经过Synchronize() 调用的方法排队

  Synchronize() 把由Method 参数传递过来的方法保存在 TThread的 FMethod字段中,而后,给线程窗口发送一个CM_EXECPROC消息,而且把消息的lParam 参数设为self(这里是值线程对象)。当线程窗口的窗口过程收到这个消息后,它就调用 FMethod字段所指定的方法。因为线程窗口是在主线程内建立的,线程窗口的窗口过程也将被主线程执行。所以,FMethod字段所指定的方法就在主线程内执行

  下图形象地说明了 Synchronize() 的内部机制和原理

 

4.用消息来同步

  能够利用在线程之间使用消息同步以替代 TThread.Synchronize() 方法。可使用API 函数SendMessage() 或 PostMessage() 来发送消息。例以下面一段用来在一个线程中设置另外一个线程中的编辑框文本的代码

1
2
3
4
5
6
var
     S:  String ;
begin
     S:=  'hello from threadland' ;
     SendMessage(SomeEdit . Handle, WM_SETTEXT,  0 Integer ( PChar (S)));
end ;

  

http://www.cnblogs.com/xumenger/p/4505104.html

相关文章
相关标签/搜索