读书人

多线程中查询数据的有关问题

发布时间: 2012-03-15 11:50:38 作者: rapoo

多线程中查询数据的问题

线程的构造函数定义如下:
constructor TBaseThread.Create(Interval: integer);
begin
inherited create(True);
Email := TMail.create;
self.Interval:=interval;
self.OnTimer:= doAction;
freeonterminate:=true;
cs:=tcriticalsection.Create;

with TAstaBaseClientDataSet.Create(nil) do
begin
AstaClientSocket := DM.cltSocket;
SQL.Text := 'select * from Table ';
Open;
sTemplatePath := FieldByName('template_path').AsString;
sDestPath := FieldByName('local_send_path').AsString;
Free;
end;
end;


线程的执行代码如下:(就是一个定时执行功能)
procedure TBaseThread.Execute;
var
i:integer;
begin
inherited;
while not terminated do
begin
cs.Enter;
i:=interval;
cs.Leave;
sleep(i);
cs.Enter;
try
if assigned(ontimer)then
ontimer(self);
finally
cs.Leave;
end;
end;

end;

调用方法1:
Thd := TBaseThread.create(1000);
Thd.SetEnabled(true);
SetEnabled方法的代码如下:
procedure TBaseThread.SetEnabled(Enabled: boolean);
begin
if enabled then
resume
else
suspend;
end;
//这种调用方法会报错:checkSynchronize called from thread $F2C, which is NOT the main thread

调用方法2:
Thd := TBaseThread.create(1000);
Thd.Execute; //这样调用数据能正常导入导出,可是主界面会假死,因为线程永远不会停止

请教解决方法,谢谢

[解决办法]
把构造函数改一下
constructor TBaseThread.Create(Interval: integer;suspended:boolean);
begin
inherited create(suspended);
....
suspended决定挂起还是执行
[解决办法]
调整下你的思路吧,先生,为啥要一条道走到黑,前辈的经验不吸取,非要自己创造,然后处处碰壁,就你这个东西,把create函数做好了将会使你事半功倍
[解决办法]
如果用Timer,肯定不行(因为Timer在同一时间只有一个Timer会执行) 所以只有改
你怎么知道不行,可以同时好几个TTimer1,TTimer2,TTimer3
procedure TForm1.Timer1Timer(Sender: TObject);
begin

end;

procedure TForm1.Timer2Timer(Sender: TObject);
begin

end;

procedure TForm1.Timer3Timer(Sender: TObject);
begin

end;

[解决办法]
如果用Timer,肯定不行(因为Timer在同一时间只有一个Timer会执行) 所以只有改
你怎么知道不行,可以同时好几个TTimer1,TTimer2,TTimer3
procedure TForm1.Timer1Timer(Sender: TObject);
begin

end;

procedure TForm1.Timer2Timer(Sender: TObject);
begin

end;

procedure TForm1.Timer3Timer(Sender: TObject);
begin

end;

[解决办法]
如果用Timer,肯定不行(因为Timer在同一时间只有一个Timer会执行) 所以只有改
你怎么知道不行,可以同时好几个TTimer1,TTimer2,TTimer3
procedure TForm1.Timer1Timer(Sender: TObject);
begin

end;

procedure TForm1.Timer2Timer(Sender: TObject);
begin

end;

procedure TForm1.Timer3Timer(Sender: TObject);
begin

end;

[解决办法]
[color=#FF0000][/color]那好,我给你指一下你所犯的错误,看你应该不应该好好学习
线程的构造函数定义如下:
constructor TBaseThread.Create(Interval: integer);
begin
inherited create(True); //你这儿的true让线程直接执行
Email := TMail.create;
self.Interval:=interval;
self.OnTimer:= doAction; //在线程里还要设置定时器,真服了你了
freeonterminate:=true;
cs:=tcriticalsection.Create; //这个东西应该放在主线程中

with TAstaBaseClientDataSet.Create(nil) do
begin
AstaClientSocket := DM.cltSocket;
SQL.Text := 'select * from Table ';


Open;
sTemplatePath := FieldByName( 'template_path ').AsString;
sDestPath := FieldByName( 'local_send_path ').AsString;
Free;
end;
end;


线程的执行代码如下:(就是一个定时执行功能)
procedure TBaseThread.Execute;
var
i:integer;
begin
inherited;
while not terminated do
begin
cs.Enter;
i:=interval;
cs.Leave;
sleep(i);
cs.Enter;
try
if assigned(ontimer)then
ontimer(self); //看看这儿是什么,主线程的东西放线程里了
finally
cs.Leave; //又是把主线程的东西放这儿了
end;
end;

end;

调用方法1:
Thd := TBaseThread.create(1000);//这儿线程已经运行了
Thd.SetEnabled(true); //又让它运行,真是多此一举
SetEnabled方法的代码如下:
procedure TBaseThread.SetEnabled(Enabled: boolean);
begin
if enabled then
resume
else
suspend;
end;
//这种调用方法会报错:checkSynchronize called from thread $F2C, which is NOT the main thread

调用方法2:
Thd := TBaseThread.create(1000);
Thd.Execute; //这样调用数据能正常导入导出,可是主界面会假死,因为线程永远不会停止 还加这句干什么,已经运行了的线程,还execute


[解决办法]
:-)
[解决办法]
asta这种方式还没用过,不知道多线程支持如何。ADO的话,貌似是要一个线程一个connection的。跟“DM.cltSocket”不知道有没关系。

不过话说临界区确实应该定义在主线程了,不然各个线程都有自己的临界区实例,就等于形同虚设了。
[解决办法]
ontimer(self);
我比较关心这个事件内,在做什么工作
可是主界面会假死,因为线程永远不会停止 主界面假死和线程不停止应该没多大关系,你里面有Sleep的。

[解决办法]
with TAstaBaseClientDataSet.Create(nil) do
begin
AstaClientSocket := DM.cltSocket;
SQL.Text := 'select * from Table ';
Open;
sTemplatePath := FieldByName( 'template_path ').AsString;
sDestPath := FieldByName( 'local_send_path ').AsString;
Free;
end;
创建线程时执行这个也费时间吧。不如放在Execute 里先执行。

while not terminated do
begin
cs.Enter;
i:=interval;
cs.Leave;
sleep(i);
cs.Enter;
try
if assigned(ontimer)then
ontimer(self);
finally
cs.Leave;
end;
end;
这里是在调用定时器吗?没有必要吧。直接查询数据库就就可以了,将结果保存在一个列表中,读取完成后给窗体发一个消息,然后在开始显示或进行其它的处理。

线程和消息结合使用才能真正的有效果。

[解决办法]
zyxwl@263.net
[解决办法]
while not terminated do
begin
cs.Enter;
i:=interval;
cs.Leave;
sleep(i);
cs.Enter;
try
if assigned(ontimer)then
ontimer(self);
finally
cs.Leave;
end;
end;
这里是在调用定时器吗?没有必要吧。直接查询数据库就就可以了,将结果保存在一个列表中,读取完成后给窗体发一个消息,然后在开始显示或进行其它的处理。
===============================
有必要置定器,出在ontimer(self); 查面是否有用主程的西,若有,最好把定器事件改掉,用sync理
[解决办法]
和窗体交互尽量使用POSTMESSAGE消息。
-----------------------------------
请教一下,如果象是线程创建TreeView这样的,用PostMessage会不会比较难处理呢。
[解决办法]
ASTA中人家不是已经写好多线程数据查询的方法了吗?有必要自己再写吗?见帮助中的ThreadedDBUtilityEvent、ThreadedUtilityEvent方法。


[解决办法]
up

读书人网 >.NET

热点推荐