如题1:线程代码constructor TClientPrintThread.Create(var Grid: TtsGrid; Suspended:Boolean);
begin
inherited Create(Suspended);
FSendData:=TSendData.create; //是个发送数据的对象,封装了发送数据函数
SGrid:=Grid
FreeOnTerminate := false; //线程执行完,不释放end;
destructor TClientPrintThread.Destroy;
begin
inherited;
end;procedure TClientPrintThread.Execute;
begin
while not Terminated do
begin
try
//开始发送数据
FSendData.SendText;
finally
end;
Suspend;
end;
end;//线程创建7个
for i:=1 to 7
begin
FClientPrintThread[i]:=TClientPrintThread.create(Grid[i],true) //线程创建后挂起
FClientPrintThread[i].resume; //启动多线程
end;
//然后调用对象 执行循环发送Procedure FSendData.SendText;
var
I:integer;
begin
for i:=1 to do 10000 then
begin
application.ProcessMessages;
//向com口发送数据 代码忽略
end;end;//问题:7个多线程里 有1~2个多线程一段时间后会没有反应,停止向端口发送数据了,多线程也无法访问,执行挂起或者唤醒时提示 错误 “拒绝访问”来者有分!!!!
begin
inherited Create(Suspended);
FSendData:=TSendData.create; //是个发送数据的对象,封装了发送数据函数
SGrid:=Grid
FreeOnTerminate := false; //线程执行完,不释放end;
destructor TClientPrintThread.Destroy;
begin
inherited;
end;procedure TClientPrintThread.Execute;
begin
while not Terminated do
begin
try
//开始发送数据
FSendData.SendText;
finally
end;
Suspend;
end;
end;//线程创建7个
for i:=1 to 7
begin
FClientPrintThread[i]:=TClientPrintThread.create(Grid[i],true) //线程创建后挂起
FClientPrintThread[i].resume; //启动多线程
end;
//然后调用对象 执行循环发送Procedure FSendData.SendText;
var
I:integer;
begin
for i:=1 to do 10000 then
begin
application.ProcessMessages;
//向com口发送数据 代码忽略
end;end;//问题:7个多线程里 有1~2个多线程一段时间后会没有反应,停止向端口发送数据了,多线程也无法访问,执行挂起或者唤醒时提示 错误 “拒绝访问”来者有分!!!!
但,楼主的代码是指向一个COM口,7次并发操作,可能造成COM缓冲池涨满而阻塞,形成线程被动挂起,停止响应.
FreeOnTerminate := false; //线程执行完,不释放
不知你这句意思是什么,为什么不释放
另外在
Procedure FSendData.SendText;
var
I:integer;
begin
for i:=1 to do 10000 then
begin
application.ProcessMessages;
//向com口发送数据 代码忽略
end;
里加上try语句,更好一点,因为由于硬件的原因,难保在执行时不出现错误,例如楼上所说的,这样程序会更键壮
1.Destroy方法你既然不做任何另外的操作为什么要去覆盖它.(不知道你这里是不是用了override关键字)而根据FSendData是在Create里创建的,那你应该是
在这里做FSendData的Free操作,然后再inherited Destroy;
2.SendText既然是在execute里的,而且也不是在Synchronize里用,那就是说它只要不要使用到界面上的组件,
application.ProcessMessages;这句代码就最好删掉,如果有用到界面上的组件,那你就该把这个操作放到
Synchronize里去做,而不该在这里使用application.ProcessMessages否则就失去了效率.
3.for i:=1 to do 10000 then 这里好象语法错了吧.既然while not Terminated do了再加for到10000的循环,怎么看怎么别扭.
此程序 是多个线程 向多个Com口发送数据,每次可能循环发送几万次才能结束,
Procedure FSendData.SendText;
是否应该有Com口号码参数?否则,如果采用应用程序轮询方式判断端口是否空闲,再作标记,不允许别人访问,最后释放标记,好像不太合理.很容易造成死锁.
Procedure FSendData.SendText;
var
I:integer;
begin
for i:=1 to do 10000 then
begin
//application.ProcessMessages; 不推荐使用此过程
Sleep(10); //建议强制让Com休息一下,嘻嘻
//向com口发送数据 代码忽略
end;
2.楼主也许曲解了多线程.
3.给你一个例子,不知是否对你有所启发,代码以下:{前题是例子的线程是建立在窗体单元中,用临界给线程空间}
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
deletecriticalsection(cs);//清除临界区
end;procedure TForm1.FormCreate(Sender: TObject);
begin
initializecriticalsection(cs); //创建临界区
end;{---------------线程的声明---------------}
ThztopyThread=class(TThread)
private
FAdoTable:TADOTable;
FForm:TForm1;
Fco:^boolean;
Fs,Fe:integer;
protected
procedure Execute;override;
public
constructor Create(AdoTable:TADOTable;Form:TForm1;s:integer;e:integer;var co:boolean);
destructor Destroy;override;
end;
var
Form1: TForm1;
threadrunning:integer;{--启动了的线程个数--}
co:boolean;
t1,t2,t3,t4,t5,t6,t7:ThztopyThread;{--------7个线程变量--------------}
cs:trtlcriticalsection; //线程临界区变量
implementation
destructor ThztopyThread.Destroy;
begin
FAdoTable.Active:=false;
FAdoTable.Free;
inherited Destroy;end;constructor ThztopyThread.Create(AdoTable:TADOTable;Form:TForm1;s:integer;e:integer;var co:boolean);
begin
{---代码略----}
inherited Create(False);
end;procedure ThztopyThread.Execute ;
begin
freeonterminate:=true;
entercriticalsection(cs); //------------进入临界区
{--执行的代码略--}
end;
procedure TForm1.We_ani(sender:tobject);{线程执行完毕所调用的过程}
begin
threadrunning:=threadrunning-1;{线程个数减一}
if threadrunning<=0 then begin
messagebox(Handle,'全部线程执行完毕','提示',MB_ICONINFORMATION);
end;
leavecriticalsection(cs); {离开临界区}
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
threadrunning:=7; t1:=ThztopyThread.Create(ADOTable1,Form1,0,l1,co);
t1.OnTerminate:= We_ani; t2:=ThztopyThread.Create(ADOTable1,Form1,l1,l2+l1,co);
t2.OnTerminate:= We_ani; t3:=ThztopyThread.Create(ADOTable1,Form1,l1+l2,l1+l2+l3,co);
t3.OnTerminate:= We_ani; t4:=ThztopyThread.Create(ADOTable1,Form1,l1+l2+l3,l1+l2+l3+l4,co);
t4.OnTerminate:= We_ani; t5:=ThztopyThread.Create(ADOTable1,Form1,l1+l2+l3+l4,l1+l2+l3+l4+l5,co);
t5.OnTerminate:= We_ani; t6:=ThztopyThread.Create(ADOTable1,Form1,l1+l2+l3+l4+l5,l1+l2+l3+l4+l5+l6,co);
t6.OnTerminate:= We_ani; t7:=ThztopyThread.Create(ADOTable1,Form1,l1+l2+l3+l4+l5+l6,l7,co);
t7.OnTerminate:= We_ani;
end;
以上每个线程创建时都进入一个临界区,当执行完了就会离开临界区,以此可给每个线程有执行空间.
begin
inherited Create(Suspended);
FSendData:=TSendData.create; //是个发送数据的对象,封装了发送数据函数
SGrid:=Grid
FreeOnTerminate := false; //线程执行完,不释放 end;
destructor TClientPrintThread.Destroy;
begin
inherited;
end; procedure TClientPrintThread.Execute;
begin
while not Terminated do
begin
try
//开始发送数据
FSendData.SendText;
finally
end;
//Suspend;
end;
end; //线程创建7个
for i:=1 to 7
begin
FClientPrintThread[i]:=TClientPrintThread.create(Grid[i],true) //线程创建后挂起
FClientPrintThread[i].resume; //启动多线程
end;
//然后调用对象 执行循环发送 Procedure FSendData.SendText;
var
I:integer;
begin
for i:=1 to do 10000 then
begin
//application.ProcessMessages; --->
Sleep(10);
//向com口发送数据 代码忽略
end; end;
还有要指出的是,你的这种循环暂停,resume的模式一定是有问题的.你不妨用完成端口,或者用同步事件,信号量等来处理这个问题.
在没有信号的时候让线程等待(WaitforSingleobject,而不是用sleep)直到读取到数据后发送消息等方法来实现.
begin
FClientPrintThread[i]:=TClientPrintThread.create(Grid[i],true) //线程创建后挂起
FClientPrintThread[i].resume; //启动多线程
end; 這段代碼,樓主有沒有時過用try finally end
看能執行幾個線程