关于VCL的TThread的问题

uncarman 2002-04-08 10:13:09
不知道各位对TThread的性能感觉如何,在两个TThread的派生类的execute事件中定义一个循环语句,使两个线程轮询。在循环语句中调用同一个全局变量,这个全局变量可以是普通变量也可以是指针,如PChar,PInteger等,我在线程创建前已给指针全局变量分配好内存空间,并且在线程运行过程中不执行stralloc,strdispose等操作,程序可以运行不报错,但时间一久,程序有死机现象出现,不知道是否是我上述做法欠安全。不知道大伙有没有解决方法,请指点。
...全文
82 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
uncarman 2002-04-19
  • 打赏
  • 举报
回复
解决了,谢谢各位。
uncarman 2002-04-17
  • 打赏
  • 举报
回复
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?这样写能解决问题吗?

rwdx 2002-04-08
  • 打赏
  • 举报
回复
使用API函数建立多线程,然后自己同步线程,很稳定
uncarman 2002-04-08
  • 打赏
  • 举报
回复
TThread的Synchronize(Method: TThreadMethod)方法可以将method交由主线程执行,避免多线程冲突,但这样等于没有使用多线程性能。
能不能提供线程三种同步方式的示例,多谢啦。
lastshrill 2002-04-08
  • 打赏
  • 举报
回复
两个线程同时对同一资源访问,要用线程同步比较好
线程同步有3种方法:互斥,临界区,信号量
suvi 2002-04-08
  • 打赏
  • 举报
回复
全局变量的访问一定要用TCriticalSection(为什么不用TSimpleEvent, TEvent?搞那么负责干什么,在一个application中的thread,用TCriticalSection就足够啦)
访问数据前:TCriticalSection.enter,访问完毕后用TCriticalSection.leave

祝你好运
shaw_jansin 2002-04-08
  • 打赏
  • 举报
回复
是资源冲突还是CPU过忙造成的吗?
application.ProcessMessages();
copy_paste 2002-04-08
  • 打赏
  • 举报
回复
应该不管Thread什么问题,可能是由于你的线程中访问全局对象/变量所致。
线程访问全局对象/变量,或者是引用关系的对象时,需要同步的支持,不然的话会经常出现“地址访问错: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,别的线程才能waitfor

WaitFor ==> WaitForSingleObject, WaitForMutpleObjects, Msg....

还有TCriticalSection就比较简单了,不说了
具体方面具体使用了,看它适合哪方面。
最后记住CloseHandle(Event/Semaphore/Mutex);

你说的Semaphore就是CreateSemaphore之类的。
uncarman 2002-04-08
  • 打赏
  • 举报
回复
以下是我定义的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 ;
begin

if planed then begin
Current:=0;
while current<Times do begin
DoCommand;
Inc(Current);
end;
end
else

while 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;//case

end;

我在这两个线程的execute过程中使用死循环不断执行一些过程,这些过程访问了相同的全局变量,全局变量多为pchar,在这两个线程创建之前已经分配内存。程序不够稳定,有死机现象。如何解决。
rwdx(任我独行) ,请问你有没有API线程函数的demo,我在MSDN中只有函数说明,没有demo.
哦,对了,semaphore是什么工具,我这里没有。
lastshrill 2002-04-08
  • 打赏
  • 举报
回复
我给你贴个例子,是Delphi5开发人员指南里的
用的是互斥
unit Main;

interface

uses
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.
uncarman 2002-04-08
  • 打赏
  • 举报
回复
CreateThread(),ExitThread(),ResumeThread()等API函数怎么用,能不能提供delphi的示例让我瞧瞧。
Larky 2002-04-08
  • 打赏
  • 举报
回复
轮训是最差的选择,因为浪费CPU资源而且自己做的标志可能会遇到问题比如两个线程都比较发现标志为空,然后这时候一个线程改变了标志为占用,另一个线程应该不能运行但是因为在前一个线程改变标志之前他一判断结束所以他会认为也执行,这样就会出现错误导致四季。
最简单的方法就是用操作系统提供的同步机制正如洪峰鸟所说,这几个东西很简单帮助里有很好的例子,你可以在帮助里查找我这里没有装Delphi也没有Msdn所以没法给你查。
你就查semaphore就可以了

5,379

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧