当前位置:文档之家› Delphi多线程之Semaphore (信号对象)

Delphi多线程之Semaphore (信号对象)

Delphi多线程之Semaphore (信号对象)
Delphi多线程之Semaphore (信号对象)

Delphi多线程之Semaphore(信号对象)

之前已经有了两种多线程的同步方法:

CriticalSection(临界区)和Mutex(互斥),这两种同步方法差不多,只是作用域不同; CriticalSection(临界区)类似于只有一个蹲位的公共厕所,只能一个个地进;

Mutex(互斥)对象类似于接力赛中的接力棒,某一时刻只能一个人持有,谁拿着谁跑.

什么是Semaphore(信号或叫信号量)呢?

譬如到银行办业务、或者到车站买票,原来只有一个服务员,不管有多少人排队等候,业务只能一个个地来.

假如增加了业务窗口,可以同时受理几个业务呢?

这就类似与Semaphore对象,Semaphore可以同时处理等待函数(如:WaitForSingleObject)申请的几个线程.

Semaphore的工作思路如下:

1、首先要通过CreateSemaphore(安全设置,初始信号数,信号总数,信号名称)建立信号对象;

参数四:和Mutex一样,它可以有个名称,也可以没有,本例就没有要名称(nil);有名称的一般用于跨进程.

参数三:信号总数,是Semaphore最大处理能力,就像银行一共有多少个业务窗口一样;

参数二:初始信号数,这就像银行的业务窗口很多,但打开了几个可不一定,如果没打开和没有一样;

参数一:安全设置和前面一样,使用默认(nil)即可.

2、要接受Semaphore服务(或叫协调)的线程,同样需要用等待函数(如:WaitForSingleObject)排队等候;

3、当一个线程使用完一个信号,应该用ReleaseSemaphore(信号句柄,1,nil)让出可用信号给其他线程;

参数三:一般是nil,如果给个数字指针,可以接受到此时(之前)总共闲置多少个信号;

参数二:一般是1,表示增加一个可用信号;

如果要增加CreateSemaphore时的初始信号,也可以通过ReleaseSemaphore.

4、最后,作为系统内核对象,要用CloseHandle关闭.

另外,在Semaphore的总数是1的情况下,就和Mutex(互斥)一样了.

在本例中,每点击按钮,将建立一个信号总数为5的信号对象,初始信号来自Edit1;同时有5个线程去排队.

本例也附上了Delphi中TSemaphore类的例子,但没有过多地纠缠于细节,是为了尽快理出多线程的整体思路.

--------------------------------------------------------------------------------

本例效果图:

--------------------------------------------------------------------------------

代码文件:

--------------------------------------------------------------------------------

unit Unit1;

interface

uses

Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms, Dialogs,StdCtrls;

type

TForm1=class(TForm)

Button1:TButton;

Edit1:TEdit;

procedure Button1Click(Sender:TObject);

procedure FormCreate(Sender:TObject);

procedure FormDestroy(Sender:TObject);

procedure Edit1KeyPress(Sender:TObject;var Key:Char);

end;

var

Form1:TForm1;

implementation

{$R*.dfm}

var

f:Integer;{用这个变量协调一下各线程输出的位置} hSemaphore:THandle;{信号对象的句柄}

function MyThreadFun(p:Pointer):DWORD;stdcall;

var

i,y:Integer;

begin

Inc(f);

y:=20*f;

if WaitForSingleObject(hSemaphore,INFINITE)=WAIT_OBJECT_0then begin

for i:=0to1000do

begin

Form1.Canvas.Lock;

Form1.Canvas.TextOut(20,y,IntToStr(i));

Form1.Canvas.Unlock;

Sleep(1);{以免Canvas忙不过来}

end;

end;

ReleaseSemaphore(hSemaphore,1,nil);

Result:=0;

end;

procedure TForm1.Button1Click(Sender:TObject);

var

ThreadID:DWORD;

begin

{不知是不是之前创建过Semaphore对象,假如有先关闭} CloseHandle(hSemaphore);

{创建Semaphore对象}

hSemaphore:=CreateSemaphore(nil,StrToInt(Edit1.Text),5,nil); Self.Repaint;

f:=0;

CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID); CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID); CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID); CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID); CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID);

end;

{让Edit只接受12345五个数}

procedure TForm1.Edit1KeyPress(Sender:TObject;var Key:Char); begin

if not CharInSet(Key,['1'..'5'])then Key:=#0;

end;

procedure TForm1.FormCreate(Sender:TObject);

begin

Edit1.Text:='1';

end;

procedure TForm1.FormDestroy(Sender:TObject);

begin

CloseHandle(hSemaphore);

end;

end.

--------------------------------------------------------------------------------窗体文件:

--------------------------------------------------------------------------------

object Form1:TForm1

Left=0

Top=0

Caption='Form1'

ClientHeight=140

ClientWidth=192

Color=clBtnFace

Font.Charset=DEFAULT_CHARSET

Font.Color=clWindowText

Font.Height=-11

https://www.doczj.com/doc/b517986899.html,='Tahoma'

Font.Style=[]

OldCreateOrder=False

OnCreate=FormCreate

PixelsPerInch=96

TextHeight=13

object Button1:TButton

Left=109

Top=107

Width=75

Height=25

Caption='Button1'

TabOrder=0

OnClick=Button1Click

end

object Edit1:TEdit

Left=109

Top=80

Width=75

Height=21

TabOrder=1

Text='Edit1'

OnKeyPress=Edit1KeyPress

end

end

--------------------------------------------------------------------------------

再用SyncObjs单元下的TSemaphore类实现一次,使用方法差不多,运行效果也一样: --------------------------------------------------------------------------------

unit Unit1;

interface

uses

Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,

Dialogs,StdCtrls;

type

TForm1=class(TForm)

Button1:TButton;

Edit1:TEdit;

procedure Button1Click(Sender:TObject);

procedure FormCreate(Sender:TObject);

procedure FormDestroy(Sender:TObject);

procedure Edit1KeyPress(Sender:TObject;var Key:Char);

end;

var

Form1:TForm1;

implementation

{$R*.dfm}

uses SyncObjs;

f:Integer;

MySemaphore:TSemaphore;

function MyThreadFun(p:Pointer):DWORD;stdcall;

var

i,y:Integer;

begin

Inc(f);

y:=20*f;

if MySemaphore.WaitFor(INFINITE)=wrSignaled then

begin

for i:=0to1000do

begin

Form1.Canvas.Lock;

Form1.Canvas.TextOut(20,y,IntToStr(i));

Form1.Canvas.Unlock;

Sleep(1);

end;

end;

MySemaphore.Release;

Result:=0;

end;

procedure TForm1.Button1Click(Sender:TObject);

var

ThreadID:DWORD;

begin

if Assigned(MySemaphore)then MySemaphore.Free; MySemaphore:=TSemaphore.Create(nil,StrToInt(Edit1.Text),5,''); Self.Repaint;

f:=0;

CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID); CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID); CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID); CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID); CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID);

end;

{让Edit只接受12345五个数}

procedure TForm1.Edit1KeyPress(Sender:TObject;var Key:Char); begin

if not CharInSet(Key,['1'..'5'])then Key:=#0;

end;

procedure TForm1.FormCreate(Sender:TObject);

begin

Edit1.Text:='1';

procedure TForm1.FormDestroy(Sender:TObject);

begin

if Assigned(MySemaphore)then MySemaphore.Free;

end;

end.

--------------------------------------------------------------------------------原文地址:https://www.doczj.com/doc/b517986899.html,/book/7/

相关主题
相关文档 最新文档