我给你贴个例子,是Delphi5开发人员指南里的 用的是互斥 unit Main;interfaceuses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;type TMainForm = class(TForm) Button1: TButton; ListBox1: TListBox; procedure Button1Click(Sender: TObject); private procedure ThreadsDone(Sender: TObject); end; TFooThread = class(TThread) protected procedure Execute; override; end;var MainForm: TMainForm;implementation{$R *.DFM}const MaxSize = 128;var NextNumber: Integer = 0; DoneFlags: Integer = 0; GlobalArray: array[1..MaxSize] of Integer; hMutex: THandle = 0;function GetNextNumber: Integer; begin Result := NextNumber; // return global var Inc(NextNumber); // inc global var end;procedure TFooThread.Execute; var i: Integer; begin FreeOnTerminate := True; OnTerminate := MainForm.ThreadsDone; if WaitForSingleObject(hMutex, INFINITE) = WAIT_OBJECT_0 then begin for i := 1 to MaxSize do begin GlobalArray[i] := GetNextNumber; // set array element Sleep(5); // let thread intertwine end; end; ReleaseMutex(hMutex); end;procedure TMainForm.ThreadsDone(Sender: TObject); var i: Integer; begin Inc(DoneFlags); if DoneFlags = 2 then // make sure both threads finished begin for i := 1 to MaxSize do { fill listbox with array contents } Listbox1.Items.Add(IntToStr(GlobalArray[i])); CloseHandle(hMutex); end; end;procedure TMainForm.Button1Click(Sender: TObject); begin hMutex := CreateMutex(nil, False, nil); TFooThread.Create(False); // create threads TFooThread.Create(False); end; end.
以下是我定义的TThread派生类: TDoorThread=class(TThread) private Current:smallint; InterTimes:Integer; //线程轮询间隔 ThreadMode:byte; //线程模式,1-人工,2-自动,3-计划 ThreadActed:boolean; //标示线程是否工作 Successed:boolean; //标示当前门控器数据采集是否成功 procedure GatherDoorData; //采集刷卡记录 procedure CheckAuthor; //检测UserAuthor表中是否有记录,有则导入Periods表并下载 procedure DownLoadPeriods(address:smallint); procedure DecodeSetting(OldSetting:string); public procedure execute;override; end;TCommandThread=class(TThread) private Current:smallint; InterTimes:Integer; //线程轮询间隔 ThreadActed:boolean; //标示线程是否工作 procedure DoCommand; //执行WEB命令,操作门控器 public procedure execute;override; end;以下是执行过程定义 procedure TCommandThread.execute ; beginif planed then begin Current:=0; while current<Times do begin DoCommand; Inc(Current); end; end elsewhile true do begin try Sleep(1000*InterTimes); DoCommand; if not ThreadActed then exit; except continue; end; end; //while end;procedure TDoorthread.execute ; begin case ThreadMode of 1: begin GatherDoorData; CheckAuthor; end; 2: while true do begin Sleep(1000*InterTimes); GatherDoorData; CheckAuthor; if not ThreadActed then exit; end; //while 3: begin Current:=0; while current<Times do begin GatherDoorData; CheckAuthor; Inc(Current); end; //while end;end;//caseend;我在这两个线程的execute过程中使用死循环不断执行一些过程,这些过程访问了相同的全局变量,全局变量多为pchar,在这两个线程创建之前已经分配内存。程序不够稳定,有死机现象。如何解决。 rwdx(任我独行) ,请问你有没有API线程函数的demo,我在MSDN中只有函数说明,没有demo. 哦,对了,semaphore是什么工具,我这里没有。
suvi() ,TCriticalSection在delphi帮助中没有demo,怎么用,是否这样 type TDoorThread=class(TThread) private Current:smallint; InterTimes:Integer; //线程轮询间隔 ThreadMode:byte; //线程模式,1-人工,2-自动,3-计划 ThreadActed:boolean; //标示线程是否工作 Successed:boolean; //标示当前门控器数据采集是否成功 procedure GatherDoorData; //采集刷卡记录 procedure CheckAuthor; //检测UserAuthor表中是否有记录,有则导入Periods表并下载 procedure DownLoadPeriods(address:smallint); procedure DecodeSetting(OldSetting:string); public procedure execute;override; end; var iCriticalSection:TCriticalSetion;procedure Tform1.create(Sender: TObject); begin iCriticalSection:=TCriticalSetion.create; end;procedure TDoorthread.execute ; begin iCriticalSection.enter; //加上这句case ThreadMode of 1: begin GatherDoorData; CheckAuthor; end; 2: while true do begin Sleep(1000*InterTimes); GatherDoorData; CheckAuthor; if not ThreadActed then exit; end; //while 3: begin Current:=0; while current<Times do begin GatherDoorData; CheckAuthor; Inc(Current); end; //while end;end;//case iCriticalSection.leave;//加上这句end;其他的线程execute方法中也写上上述两句iCriticalSection.enter和TCriticalSection.leave?这样写能解决问题吗?
最简单的方法就是用操作系统提供的同步机制正如洪峰鸟所说,这几个东西很简单帮助里有很好的例子,你可以在帮助里查找我这里没有装Delphi也没有Msdn所以没法给你查。
你就查semaphore就可以了
用的是互斥
unit Main;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;type
TMainForm = class(TForm)
Button1: TButton;
ListBox1: TListBox;
procedure Button1Click(Sender: TObject);
private
procedure ThreadsDone(Sender: TObject);
end; TFooThread = class(TThread)
protected
procedure Execute; override;
end;var
MainForm: TMainForm;implementation{$R *.DFM}const
MaxSize = 128;var
NextNumber: Integer = 0;
DoneFlags: Integer = 0;
GlobalArray: array[1..MaxSize] of Integer;
hMutex: THandle = 0;function GetNextNumber: Integer;
begin
Result := NextNumber; // return global var
Inc(NextNumber); // inc global var
end;procedure TFooThread.Execute;
var
i: Integer;
begin
FreeOnTerminate := True;
OnTerminate := MainForm.ThreadsDone;
if WaitForSingleObject(hMutex, INFINITE) = WAIT_OBJECT_0 then
begin
for i := 1 to MaxSize do
begin
GlobalArray[i] := GetNextNumber; // set array element
Sleep(5); // let thread intertwine
end;
end;
ReleaseMutex(hMutex);
end;procedure TMainForm.ThreadsDone(Sender: TObject);
var
i: Integer;
begin
Inc(DoneFlags);
if DoneFlags = 2 then // make sure both threads finished
begin
for i := 1 to MaxSize do
{ fill listbox with array contents }
Listbox1.Items.Add(IntToStr(GlobalArray[i]));
CloseHandle(hMutex);
end;
end;procedure TMainForm.Button1Click(Sender: TObject);
begin
hMutex := CreateMutex(nil, False, nil);
TFooThread.Create(False); // create threads
TFooThread.Create(False);
end;
end.
TDoorThread=class(TThread)
private
Current:smallint;
InterTimes:Integer; //线程轮询间隔
ThreadMode:byte; //线程模式,1-人工,2-自动,3-计划
ThreadActed:boolean; //标示线程是否工作
Successed:boolean; //标示当前门控器数据采集是否成功
procedure GatherDoorData; //采集刷卡记录
procedure CheckAuthor; //检测UserAuthor表中是否有记录,有则导入Periods表并下载
procedure DownLoadPeriods(address:smallint);
procedure DecodeSetting(OldSetting:string);
public
procedure execute;override;
end;TCommandThread=class(TThread)
private
Current:smallint;
InterTimes:Integer; //线程轮询间隔
ThreadActed:boolean; //标示线程是否工作
procedure DoCommand; //执行WEB命令,操作门控器
public
procedure execute;override;
end;以下是执行过程定义
procedure TCommandThread.execute ;
beginif planed then begin
Current:=0;
while current<Times do begin
DoCommand;
Inc(Current);
end;
end
elsewhile true do begin
try
Sleep(1000*InterTimes);
DoCommand;
if not ThreadActed then exit;
except
continue;
end;
end; //while
end;procedure TDoorthread.execute ;
begin
case ThreadMode of
1:
begin
GatherDoorData;
CheckAuthor;
end;
2:
while true do begin
Sleep(1000*InterTimes);
GatherDoorData;
CheckAuthor;
if not ThreadActed then exit;
end; //while
3:
begin
Current:=0;
while current<Times do begin
GatherDoorData;
CheckAuthor;
Inc(Current);
end; //while
end;end;//caseend;我在这两个线程的execute过程中使用死循环不断执行一些过程,这些过程访问了相同的全局变量,全局变量多为pchar,在这两个线程创建之前已经分配内存。程序不够稳定,有死机现象。如何解决。
rwdx(任我独行) ,请问你有没有API线程函数的demo,我在MSDN中只有函数说明,没有demo.
哦,对了,semaphore是什么工具,我这里没有。
线程访问全局对象/变量,或者是引用关系的对象时,需要同步的支持,不然的话会经常出现“地址访问错:oxfffffdfdsf",什么什么的一般我们线程访问全局对象/变量/引用的对象,最简单的用Synchrize(ProcMethod),
其它的还有:
SyncObjs.TSimpleEvent, TEvent类
CreateEvent //建立一个事件,安全,是否自动设置为无信号(waitFor完成后),初始信号,名称
WaitFor //如果设置为自动无信号,waitFor会将Event设为无信号
SetEvent //设置有信号
ResetEvent //设置无信号CreateSemaphore //建立信号,安全(nil),初始,最大引用计数器,名称
WaitFor //waitfor使Semaphore--,即说Semaphore的资源--,如超过最大计数器则阻塞进程
ReleaseSemaphore //将Semaphore++CreateMutex //互斥信号,
WaitFor //将信号lock,不成功则阻塞进程
ReleaseMutex //工作做完了,将信号UnLock,别的线程才能waitforWaitFor ==> WaitForSingleObject, WaitForMutpleObjects, Msg....还有TCriticalSection就比较简单了,不说了
具体方面具体使用了,看它适合哪方面。
最后记住CloseHandle(Event/Semaphore/Mutex);你说的Semaphore就是CreateSemaphore之类的。
application.ProcessMessages();
访问数据前:TCriticalSection.enter,访问完毕后用TCriticalSection.leave祝你好运
type
TDoorThread=class(TThread)
private
Current:smallint;
InterTimes:Integer; //线程轮询间隔
ThreadMode:byte; //线程模式,1-人工,2-自动,3-计划
ThreadActed:boolean; //标示线程是否工作
Successed:boolean; //标示当前门控器数据采集是否成功
procedure GatherDoorData; //采集刷卡记录
procedure CheckAuthor; //检测UserAuthor表中是否有记录,有则导入Periods表并下载
procedure DownLoadPeriods(address:smallint);
procedure DecodeSetting(OldSetting:string);
public
procedure execute;override;
end;
var
iCriticalSection:TCriticalSetion;procedure Tform1.create(Sender: TObject);
begin
iCriticalSection:=TCriticalSetion.create;
end;procedure TDoorthread.execute ;
begin
iCriticalSection.enter; //加上这句case ThreadMode of
1:
begin
GatherDoorData;
CheckAuthor;
end;
2:
while true do begin
Sleep(1000*InterTimes);
GatherDoorData;
CheckAuthor;
if not ThreadActed then exit;
end; //while
3:
begin
Current:=0;
while current<Times do begin
GatherDoorData;
CheckAuthor;
Inc(Current);
end; //while
end;end;//case
iCriticalSection.leave;//加上这句end;其他的线程execute方法中也写上上述两句iCriticalSection.enter和TCriticalSection.leave?这样写能解决问题吗?