timer和线程使用的问题,在线等(100分)

  • 主题发起人 主题发起人 njhuadong
  • 开始时间 开始时间
N

njhuadong

Unregistered / Unconfirmed
GUEST, unregistred user!
在一个TIMER中启动一个数据库查询线程,当时间间隔比较短时,数据查询不出来,而且一段时间后,机器会没有相应,代码如下:
unit UntThread;
interface
uses
Classes,adodb,activeX;
type
AnswerReq = class(TThread)
private
{ Private declarations }
FMsgContent : string;
FSrcAddr : string;
FDestAddr : string;
FRegState : string;
FIsRegSyc : integer;
FConnect : string;
FTemp : string;
FQuery : TAdoQuery;
FAdoCon : TAdoConnection;
protected
procedure Execute;
override;
procedure MonitorShow;
procedure MonitorTemp;
public
constructor Create(MsgContent,SrcAddr,DestAddr,RegState:string;IsRegSyc:integer;AConnect:string);
end;

implementation
uses UntMain,UntWatch,UntData, DB;
{ Important: Methods and properties of objects in VCL or CLX can only be used
in a method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure AnswerReq.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end;
}
{ AnswerReq }
constructor AnswerReq.Create(MsgContent,SrcAddr,DestAddr,RegState:string;IsRegSyc:integer;AConnect:string);
begin
FMsgContent := MsgContent;
FSrcAddr := SrcAddr;
FDestAddr := DestAddr;
FRegState := RegState;
FIsRegSyc := IsRegSyc;
FConnect := AConnect;
CoInitialize(nil);
FAdoCon := TADOConnection.create(nil);
with FAdoCondo
begin
ConnectionString := FConnect;
LoginPrompt := false;
Connected := true;
end;
FQuery := TADOQuery.Create(nil);
FQuery.Connection := FAdoCon;
inherited Create(False);
FreeOnTerminate := true;
end;

procedure AnswerReq.Execute;
var sSql : string;
AdoCon : tADoconnection;
AdoQ : tAdoQuery;
begin
{ Place thread code here }
Synchronize(MonitorShow);
if copy(FMsgContent,1,2) = 'abcd' then
begin
with FQuerydo
begin
SQL.Clear;
SQL.Add('SELECT * FROM TBTABLE');
open;
FTemp := fieldbyname('AAA').AsString;
Synchronize(MonitorTemp);
close;
end;
FQuery.Free;
FAdoCon.Free;
end;
end;

procedure AnswerReq.MonitorShow;
var sType,sContent : string;
begin
with FrmWatchdo
begin
Showbegin
fo('开始线程!');
end;
end;

procedure AnswerReq.MonitorTemp;
begin
with FrmWatchdo
begin
ShowFailInfo(FTemp);
end;
end;

end.

TIMER 调用:
with AnswerReq.Create(StrPas(MsgContent),StrPas(SrcAddr),StrPas(DestAddr),strpas(RegState),IsRegSync,sConnect)do
OnTerminate := Threadend;
 
你在你的OnTimer事件中使用全局变量做标识来看是否创建线程:
if not AllowCreateThread then
Exit;
with AnswerReq.Create(StrPas(MsgContent),StrPas(SrcAddr),StrPas(DestAddr),strpas(RegState),IsRegSync,sConnect)do
OnTerminate := Threadend;
然后再ThreadEnd事件中将AllowCreateThread置为True就可以了。
其实就是避免上一个线程没有结束就创建新的线程。
 
to TYZhang:
那还要线程干什么呀?
 
但是这样的话,不就是单线程在做数据库查询了吗,那我使用多线程又有何意义呢
 
to LeeChange:
按照楼主的需求(定时查询数据并显示),本来就不需要线程。
 
to xeen:
“按照楼主的需求(定时查询数据并显示),本来就不需要线程。”,那就应该叫楼主换成定时器。
再说,定时查询就没必要用线程了吗?如果查询非常耗时,而主线程又非常忙碌(比如信号采集),还是用线程好吧。
 
to LeeChange:
使用线程只是避免查询占用时间导致界面没相应或影响其他界面操作,使用timer只是说查询要定期执行而已,楼主并没有说除了定时器的查询,就没有其他操作了,比如在查询时还要做输入等。
 
算了,算了,都跑题了。
楼主问的核心问题咱们一个也没谈,关键是怎么使每个并发的线程都成功的取得数据.
 
楼主的线程执行的是同样的功能:
1、如果先后执行线程的结果一致,那么少执行一个也没关系;
2、如果先后执行的结果不一致,那么最后的线程执行结果有意义;
所有定时器中间漏了个把线程没创建执行应该没关系。
 
首先这个设计思想有问题,线程是十分昂贵的系统资源。不应该在定时器中大量产生。
正确的方法是只创建一个线程,在线程中循环执行查询、显示的代码,最好每次循环后
Sleep一段时间。
 
hehe,到底是项目做多了呀,能绕就绕。
其实偶现在在工作中跟你一样,只求结果,不求过程。
哈哈,希望咱俩的老板别看见这贴。
改日喝酒。
 
to 晨哥:
没办法,那是被逼得。再说客户与老板都不懂,他也不会去关心实现过程的。[:D][:D]
 
hehe,好了,就到这吧。咱俩再这样旁若无人的聊,楼主要有意见了。
说真的,哪天真得好好聚聚。
 
究竟如何解决呀,都跑题了!
 
to njhuadong:
不是已经讲了嘛,就是设置一个全局变量,或互斥的标记等,保证你在上一个线程还没有完成的时候,在Timer的事件中不创建新的线程。
to LeeChange:
一定要聚哦。
 
但是timer事件里面有不断产生的内容,需要不断的创建线程,不可能等某个线程结束后,在创建一个新的!
 
其实这就像一个水管向水池放水,一个水管从水池排水,如果放水的速度大于排水的速度,那么水池总有满的的时候,处理只有两种方式:减少放水量,或加大排水量。
而你的线程中查询占用的时间是不可控制的,也就是说没办法通过排水来解决,那么只能通过减少放水量来解决:1、加大Timer的执行频率;2、跳过部分执行机会。
 
线程中加个工作队列不就可以了?
主线程只管定时往子线程工作队列中压入数据和操作类型。子线程不断取出队列中的数据进行相应操作,如果没有数据则进入等待状态。
这样不必定时创建线程(创建线程还是很消耗资源的),只要事先创建多个线程作为线程池,然后主线程定时以一定负载平衡算法往相应线程中压入数据即可(最简单的就是各个线程轮流压入),压入、弹出数据如果规划得好的话甚至不必同步。
 
其实你的计算机没有多cup的话,在delphi里面的线程,也不会快多少。。用timer就已经足够了
 
>>>>当时间间隔比较短时,数据查询不出来
我想,应该是时间间隔太短,也就是时间的间隔小于每次操作需要的时间。
就象我一分钟吃一个包子,你每30秒送来一个,怎么行呢?
对于TTimer,如果上次操作没有做完,那么即使时间到了,也会忽略,不会去做的。
 
后退
顶部