多线程数据库查询与主线程的问题(50分)

  • 主题发起人 主题发起人 zxa
  • 开始时间 开始时间
Z

zxa

Unregistered / Unconfirmed
GUEST, unregistred user!
我在程序中,使用线程完成数据库查询,而在主程序的INDY UDP 通讯中的UDPServerUDPRead事件中又向数据库中的表写入数据,如果udp未收到数据,线程查询很正常,主窗口也可以同时完成其他工作,可是在线程正在进行查询时一旦udp收到数据向数据库写入时,整个窗体死掉,直到线程完成查询为止,感觉就像查询线程变成了主线程.为什么?!
线程程序如下:
..
tquerythread= class(tthread)
private
FADOConnection:TADOConnection;
FADOQuery:TADOQuery;
fdatasource:tdatasource;
fqueryexception:exception;
procedure connectdatasource;
procedure showqryerror;
protected
procedure execute;override;
public
constructor create(adoconnection:tadoconnection;adoquery:tadoquery;datasource:tdatasource);virtual;
end;
...
...
constructor tquerythread.create(adoconnection:tadoconnection;adoquery:tadoquery;datasource:tdatasource);
begin
inherited create(true);
fadoconnection:=adoconnection;
fadoquery:=adoquery;
fdatasource:=datasource;
freeonterminate:=true;
resume;
end;

procedure tquerythread.execute;
begin
try
fadoquery.Open;
application.ProcessMessages;
//connectdatasource;
synchronize(connectdatasource);
except
end;

end;

procedure tquerythread.connectdatasource;
begin
fdatasource.dataset:=fadoquery;
end;

procedure tquerythread.showqryerror;
begin
application.ShowException(fqueryexception);
end;

procedure runbackgroundquery(adoconnection:tadoconnection;adoquery:tadoquery;datasource:tdatasource);
begin
tquerythread.create(adoconnection,adoquery,datasource);
end;

 
试试 FADOConnection FADOQuery在线程里创建,不要从外边传
 
我没有看到你线程里面到底好做作了什么啊。
 
runbackgroundquery(adoconnection:tadoconnection;adoquery:tadoquery;datasource:tdatasource);是主程序执行线程的执行程序
 
我把程序改成了线程内Adoquery创建,可问题依旧,为什么?
tquerythread= class(tthread) //查询用线程声明
private
FADOConnection:TADOConnection;
FADOQuery:TADOQuery;
SQLString:string;
fdatasource:tdatasource;
fqueryexception:exception;
procedure connectdatasource;
procedure showqryerror;
protected
procedure execute;override;
public
constructor create(s:string;datasource:tdatasource);virtual;
destructor destroy;override;
end;



var
mainform: Tmainform;
...
implementation
uses data, ...;
{$R *.dfm}
destructor tquerythread.destroy;
begin
//fadoconnection.Free;
//couninitialize(0);
//inherited destroy;
end;

constructor tquerythread.create(S:string;datasource:tdatasource);
begin

fadoconnection:=tadoconnection.Create(nil);
fadoquery:=tadoquery.create(nil);
SQLString:=s;
fadoquery.Connection:=fadoconnection;
with fadoconnectiondo
begin
loginprompt:=false;
keepconnection:=true;
connectionstring:='provider=Microsoft.Jet.OLEDB.4.0;Data Source=localeas.mdb;Persist Security Info=False';
end;
// with
inherited create(true);
fdatasource:=datasource;
freeonterminate:=true;
resume;
end;

procedure tquerythread.execute;
begin
try
//coinitialize(0);
fadoquery.SQL.Clear;
fadoquery.SQL.Add(SQLString);
fadoquery.Open;
//application.ProcessMessages;
//connectdatasource;
synchronize(connectdatasource);
except
end;

end;

procedure tquerythread.connectdatasource;
begin
fdatasource.dataset:=fadoquery;
end;

procedure tquerythread.showqryerror;
begin
application.ShowException(fqueryexception);
end;

procedure runbackgroundquery(s:string;datasource:tdatasource);
begin
tquerythread.create(s,datasource);
end;

主程序调用 runbackgroundquery(s:string;datasource:tdatasource);
 
把线程声明未自由线程模型,好像是
procedure execute
begin
CoInitializeEx(nil,COINIT_MULTITHREADED);
中间访问数据库部分
CoUninitialize();
end;
不要用同步方法
 
to :一只没有缺点的狼,非常感谢你的回答
能说的具体一点吗?什么是自由线程,如何做?
 
procedure tquerythread.execute;
begin
try
fadoquery.Open;
application.ProcessMessages;
//connectdatasource;
synchronize(connectdatasource);
except
end;

end;

怎么能这么写呢,受不了
application.ProcessMessages;
多余,线程有自已的消息队列与主线程无关
synchronize(connectdatasource);
//
这句话是什么意思? 这句话只会把connectdatasource这个动作与主线程同步
即把connectdatasource放到主线程中串行地执行,
如果您只是想互斥使用,您只要设一个临界区
定义一个全局临界区变量
临界区 :TCriticalSection ;
procedure tquerythread.execute;
begin
临界区.enter;
try
fadoquery.Open;
connectdatasource;
finally
临界区.leave;
end;
end;
 
自由线程是COM的一种线程模型,ADO就是COM的应用。说起起来反正很多啊,看看书吧,自由线程就是声明这种应用的一种方式,CoInitializeEx(nil,COINIT_MULTITHREADED);这就是应用这个方法的基本函数,COINIT_MULTITHREADED指定的就是一种线程模型,把你的数据库访问部分放在这个函数之后,就是已经通知COM服务应用这种模式了,然后再以CoUninitialize();结束就行了,这中间的代码和在主线程中没有什么区别,之所以采用者种方式,是为了可以绕过主线程的消息循环,使主线程可以正常运行,同时可以不使主界面失去响应
 
TO 一只没有缺点的狼:经过多次测试,我发现我的线程修改后没有问题,问题出在ACCESS上。线程在ACCESS上使用了聚合函数SUM(),YEAR()等后,由于ACCESS数据库本身不能实现SUM(),所有计算都有程序执行,才出现这样情形。所以,主线程此时一旦对此表执行操作,程序就会一直等线程结束才继续运行。换成SQL数据库就不会出现这种问题。不知为什么?!
 
多人接受答案了。
 

Similar threads

后退
顶部