Delphi多线程编程之四 线程安全和VCL
2011-10-05 13:45
183 查看
◆Delphi多线程编程之四 线程安全和VCL ◆(乌龙哈里2008-10-12)
(调试环境:Delphi2007+WinXPsp3 例程:Tst_Thread4.dpr)
由于Delphi VCL在设计成大部分在主线程访问,因而,当多个线程同时访问VCL时,就非安全。
其实线程的安全性如上面那个读全局变量来说,那个全局变量是非线程安全的,因为当另外一个线程访问它的时候,它的数值还在被前一个线程改动中。这在非线程安全的对象中就会造成很严重的后果,比如一个对象的创立时的初始值被另一个线程改变了,后果相当地严重。
VCL中,连很基础的Tlist都是非线程安全,要多个线程操纵List时,用TThreadList来替代。
unit Tst_Thread4U;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TMyThread=class(TThread)
protected
procedure Execute;override;
procedure ShowInMemo;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
const
MaxSize=1000;
var
NextNumber:Integer=0;
GlobalNum:Integer;
function GetNextNumber:Integer;
begin
Result:=NextNumber;
inc(NextNumber);
end;
{ TMyThread }
procedure TMyThread.Execute;
var
i:Integer;
begin
FreeOnTerminate:=True; //终止后自动free
for i := 1 to MaxSize do
begin
GlobalNum:=GetNextNumber;
Sleep(5);
Synchronize(ShowInMemo);
// ShowInMemo;
end;
end;
procedure TMyThread.ShowInMemo;
begin
Form1.Memo1.Lines.Add(inttostr(GlobalNum));
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
TMyThread.Create(False);
TMyThread.Create(False);
end;
end.
上面这个例程,把输出到Memo1放在线程里了,所以要在Execute()内用到Synchronize()函数,这样才是线程安全。
一、Synchronize()函数。
是个重载函数,有两种引用形式:
class procedure Synchronize(AThread: TThread; AMethod: TThreadMethod); overload;
procedure Synchronize(AMethod: TThreadMethod); overload;
Amethod是线程的一个自定义不带参数过程(!!太烦了,不能带参数,好不方便)。
Synchronize()调用了Windows的SendMessage()向主线程发一消息。主线程必须已建立消息队列,并且不断地从消息队类中检索消息。一旦主线程检索到消息,就执行Synchronize()所指定的代码。(ps:我查了Vcl源程序,发现也是调用临界区,这个太不方便了,还是使用临界区好)。
(调试环境:Delphi2007+WinXPsp3 例程:Tst_Thread4.dpr)
由于Delphi VCL在设计成大部分在主线程访问,因而,当多个线程同时访问VCL时,就非安全。
其实线程的安全性如上面那个读全局变量来说,那个全局变量是非线程安全的,因为当另外一个线程访问它的时候,它的数值还在被前一个线程改动中。这在非线程安全的对象中就会造成很严重的后果,比如一个对象的创立时的初始值被另一个线程改变了,后果相当地严重。
VCL中,连很基础的Tlist都是非线程安全,要多个线程操纵List时,用TThreadList来替代。
unit Tst_Thread4U;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TMyThread=class(TThread)
protected
procedure Execute;override;
procedure ShowInMemo;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
const
MaxSize=1000;
var
NextNumber:Integer=0;
GlobalNum:Integer;
function GetNextNumber:Integer;
begin
Result:=NextNumber;
inc(NextNumber);
end;
{ TMyThread }
procedure TMyThread.Execute;
var
i:Integer;
begin
FreeOnTerminate:=True; //终止后自动free
for i := 1 to MaxSize do
begin
GlobalNum:=GetNextNumber;
Sleep(5);
Synchronize(ShowInMemo);
// ShowInMemo;
end;
end;
procedure TMyThread.ShowInMemo;
begin
Form1.Memo1.Lines.Add(inttostr(GlobalNum));
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
TMyThread.Create(False);
TMyThread.Create(False);
end;
end.
上面这个例程,把输出到Memo1放在线程里了,所以要在Execute()内用到Synchronize()函数,这样才是线程安全。
一、Synchronize()函数。
是个重载函数,有两种引用形式:
class procedure Synchronize(AThread: TThread; AMethod: TThreadMethod); overload;
procedure Synchronize(AMethod: TThreadMethod); overload;
Amethod是线程的一个自定义不带参数过程(!!太烦了,不能带参数,好不方便)。
Synchronize()调用了Windows的SendMessage()向主线程发一消息。主线程必须已建立消息队列,并且不断地从消息队类中检索消息。一旦主线程检索到消息,就执行Synchronize()所指定的代码。(ps:我查了Vcl源程序,发现也是调用临界区,这个太不方便了,还是使用临界区好)。
相关文章推荐
- ◆Delphi多线程编程之四 线程安全和VCL ◆(乌龙哈里2008-10-12)
- ◆delphi多线程编程之一create和Free◆(乌龙哈里2008-10-11)
- 多线程编程 -- 线程安全的链表
- java并发编程-线程安全1:servlet访问统计
- C/C++编程教训----函数内静态类对象初始化非线程安全(C++11之前)
- 互联网并发编程之一 线程安全02
- 线程安全的问题,这是编程中肯定会遇到,遇到必须要解决的问题
- 多线程编程-线程安全问题浅谈(附懒汉式单例)
- C#网络编程之线程安全简述(4)
- ThreadLocal,静态变量,实例变量,局部变量的线程安全,回复:ByteBuffer 到底怎么用?网络编程中一点总结!
- 系列文章:并发编程原则与技术(一)——线程安全
- 【并发编程实战笔记】--使用锁和条件变量的线程安全队列
- Java并发编程规则:设计线程安全的类
- 设计高效的线程安全的缓存(java并发编程实战5.6)
- Java并发编程规则:无状态对象永远是线程安全的
- Java并发编程规则:有状态的线程安全对象在线程池中使用不一定就是线程安全的
- 并发编程(二):非线程安全集合类
- 多线程编程-- 线程安全的栈 stack
- 多线程编程-- 线程安全的queue II
- Java并发编程实践笔记之-什么是线程安全