Event事件用法与Mutex差不多,但它可以使用:SetEvent(启动运行)ResetEvent(暂停运行)、PulseEvent(执行一次后立即暂停)。
先看一下创建函数:CreateEvent(
lpEventAttributes: PSecurityAttributes;
bManualReset: BOOL;
bInitialState: BOOL;
lpName: PWideChar ): THandle; stdcall;
(lpEventAttributes参数,指向TSecurityAttributes记录的指针,一般可以缺省填入nil值;
bManualReset参数,是否可手动暂停,True为可手动,False为事件对象控制一次后将立即暂停;
bInitialState参数,初始状态,True为事件对象创建后处可运行状态,False为暂停状态;
lpName参数,事件的名称;
返回值为句柄。)
例子代码:
- unit Unit2;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, StdCtrls;
- type
- TForm2 = class(TForm)
- Button1: TButton;
- Label1: TLabel;
- Label2: TLabel;
- Label3: TLabel;
- Label4: TLabel;
- Label5: TLabel;
- btnSetEvent: TButton;
- btnResetEvent: TButton;
- btnPulseEvent: TButton;
- procedure Button1Click(Sender: TObject);
- procedure FormDestroy(Sender: TObject);
- procedure btnSetEventClick(Sender: TObject);
- procedure btnResetEventClick(Sender: TObject);
- procedure btnPulseEventClick(Sender: TObject);
- procedure FormCreate(Sender: TObject);
- private
- { Private declarations }
- public
- { Public declarations }
- end;
- var
- Form2: TForm2;
- hEvent:THandle;
- implementation
- uses MyThread;
- {$R *.dfm}
- procedure TForm2.btnPulseEventClick(Sender: TObject);
- begin
- PulseEvent(hEvent);
- end;
- procedure TForm2.btnResetEventClick(Sender: TObject);
- begin
- ResetEvent(hEvent);
- end;
- procedure TForm2.btnSetEventClick(Sender: TObject);
- begin
- SetEvent(hEvent);
- end;
- procedure TForm2.Button1Click(Sender: TObject);
- begin
- TMyThread.Create(Label1);
- TMyThread.Create(Label2);
- TMyThread.Create(Label3);
- TMyThread.Create(Label4);
- TMyThread.Create(Label5);
- end;
- procedure TForm2.FormCreate(Sender: TObject);
- begin
- hEvent:=CreateEvent(nil,True,True,nil);
- end;
- procedure TForm2.FormDestroy(Sender: TObject);
- begin
- CloseHandle(hEvent);
- end;
- end.{多线程类}
- unit MyThread;
- interface
- uses
- Classes,StdCtrls,SysUtils,Windows;
- type
- TMyThread = class(TThread)
- private
- { Private declarations }
- FLabel:TLabel;
- str:String;
- procedure Show;
- protected
- procedure Execute; override;
- public
- Constructor Create(aLabel:TLabel);
- end;
- implementation
- uses Unit2;
- { TMyThread }
- procedure TMyThread.Show;
- begin
- FLabel.Caption:=str;
- end;
- Constructor TMyThread.Create(aLabel: TLabel);
- begin
- FLabel:=aLabel;
- Inherited Create(False);
- end;
- procedure TMyThread.Execute;
- var
- i:Integer;
- begin
- { Place thread code here }
- FreeOnTerminate:=True;
- for i := 0 to 2000 do
- begin
- if WaitForSingleObject(hEvent,INFINITE)=WAIT_OBJECT_0 then
- begin
- if not Terminated then
- begin
- str:=Format(\'线程ID:%.4d,第%.4d个循环。\',[GetCurrentThreadId,i]);
- Show;
- //Synchronize(Show);
- end;
- end;
- end;
- end;
- end.
这里要把WaitForSingleObject放到循环中,这样才可以看到在循环的时候暂停。
这里有一个问题,有的时候会出现”Canvas does not allow drawing”错误。应该是多线程访问VCL的原因,不知道怎么修改代码。加上Lock和UnLock,程序却死掉了。
如果要将Event事件像Mutex那样使用,那么程序改成以下这样:
//创建事件中指定不允许手工暂停
- begin
- hEvent:=CreateEvent(nil,false,True,nil);
- end;
- //多线程的执行过程
- procedure TMyThread.Execute;
- var
- i:Integer;
- begin
- { Place thread code here }
- FreeOnTerminate:=True;
- if WaitForSingleObject(hEvent,INFINITE)=WAIT_OBJECT_0 then
- for i := 0 to 2000 do
- begin
- if not Terminated then
- begin
- str:=Format(\'线程ID:%.4d,第%.4d个循环。\',[GetCurrentThreadId,i]);
- Show;
- //Synchronize(Show);
- end;
- end;
- SetEvent(hEvent);
- end;