说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

Delphi多线程问题,谁能回答?

编辑:说三道四文库 发布时间:2018-04-24 07:09
HTML文档下载 WORD文档下载 PDF文档下载
为什么出错呢?

代码:
procedure TForm1.Button1Click(Sender: TObject);
begin

  ThTest:=ttest.Create(AdoQuery1);
end;

constructor ttest.Create(ADOQ: TADOQuery);
begin
ADOQuery:=ADOQ;
inherited create(false);
end;

procedure ttest.Execute;
begin

adoquery.SQL.Text:='select sum([Interval]) from Recordtab ';
adoquery.Open;//在此出错
if not (adoquery.Eof and adoquery.Bof) then
begin
  adoquery.Recordset.MoveFirst;
  GetVal:=adoQuery.Recordset.Fields[0].value;
end;

end;
主要是执行一个SQL汇总,用ADO调用MDB数据库 
补充一下,此程序在单线程下运行没问题。
另外谁能告诉我为什么ADO的所有控件打开操作完毕后关闭必须要有纪录才给关闭,而Delphi自代TTable,TQuery却没有这个问题
没人回答,俺加分,100
没人回答,俺加分,100
建议:
    做以下操作之前,先做
    adoQuery.Close;
    adoquery.SQL.Text:='select sum([Interval]) from Recordtab ';
    adoquery.Open;//在此出错
同样出错!
有没有人能回答啊?
好可怜哦,呜呜。
该我哭,你哭什么
使用Synchronize调用你的程序
Synchronize(你的程序名);
ok

Synchronize是将所执行线程的过程递交给主线程完成,此程序在主线程中运行没有问题,使用Synchronize也没有问题,但是一旦使用Synchronize,就没有办法再主线程中终止程序了,我现在做的是一个大库的查询(40万条)左右,希望能用多线程作退出查询
但你这种情况只能用Synchronize否则肯定有问题,我已经验证过了。
先通过了,然后再想别的方法。
我在三天前就通过了,程序也作的差不多,但就是心里窝火,他怎么就这么戈呢?其实用Synchronize还不如再主线程里直接做,多加个线程没有任何意义,但用TQuery没有问题,偏偏要访问mdb数据库,用Tquery还要建别名,有什么办法可以用Tquery访问MDB而不用BDE的吗?
看来Delphi的ado还是有问题。
那只能用外部组件了,否则你只能用ADO,ADO有什么问题?
我还不知道他程序的出错的提示信息是什么?
现象如下:如果在多线程中使用Tquery,可以正常打开查询,返回结果,如果相同的代码换成TADOQuery则在打开数据库时报错,错误是:
Project Project1.exe raised exception class EOleException with message '尚未调用
coinitialize.'。process stopped.use step or Run to continue.
另外如果用ADO如果数据库打开,删光所有纪录,数据库就管不上了,而用Data Access页的组件没有这个问题,这也是今天发现的 
不好意思,我在不走就没车了。
我明天再来,可以联系truest@163.com
瞎猜一下:Ado是基于com的,下面msdn上的一段关于CoInitialize的说明或许会有用。
Initializes the COM library on the current apartment and identifies the concurrency model as single-thread apartment (STA). Applications must initialize the COM library before they can call COM library functions other than CoGetMalloc and memory allocation functions. 

在关闭TADOQuery之前加一句
TADOQuery1.RecordSet.Close();
再试一试。
ADOqUERY.OPEN 就出错了
还没有解决吗?
不是灌水
那你就调用一下CoInitialize吧,在任何一个单元的initialization段中,然后在finalization中调用CoUninitialize(好象是这个名字)。
agui(阿贵) 说的对
也可以这样
在线程中调用其他单元的函数或过程来执行
注意vcl控件的执行期间调用问题
看看这样能否绕过同步问题。
constructor ttest.Create(ADOQ: TADOQuery);
begin
ADOQuery := TADOQuery.Create(nil);
ADOQuery.Asign(ADOQ);
inherited create(false);
end;

一个query关闭再执行另外一个啊,否则服务器会被你拖死的。
哇,PB的斑竹(liulee(流方) )跑到这里来了?
是多线程耶!怎么关闭在执行另一个?
关闭了在执行另一个,我还写多线程干吗?找麻烦?
richardsong(白玉老虎):DELPHI的帖子怎么跑到这里来了?再不走,我要赶了。。。。。。。。
我认为是ADO的问题。你就建个别名,用BDE吧,或者不用建别名,用DataBase连接,用文件名连接(我向来都是这样连接)。
哪个帖子跑到哪里了,说清楚!拜托
to am2000:
再者说,我又不是斑竹,我说了也不算,他自己跑过去的,我有什么办法?
是我的帖子吗?
呵呵,好像多线程我没用过似的。
你的帖子是什么啊???告诉我标题。
或者你去灌水乐园看看。。。
是不是那个“还学PB呢”那个帖子??????如果是,是我移的,呵呵。

当然是你移的,PB现在就你一个斑竹,不是你一的,难道还是我移的?还是他自己Move过去的。


还有:我没说你没用过多线程,我从来不挖苦别人,嘲笑别人或者贬低别人,这个良好作风Delphi里的弟兄可以作证,我们斑竹也可以作证的。老兄不要随便冤枉好人。
试着将
ADOQuery:=ADOQ;
inherited create(false);
这两句调过来试试看吧,我一向写新类都是先写第二句的,因为要有新类的实体,必定要先建立吗!?
如果还不行,那应该是戴妃与M$不和了.

to: 
richardsong(白玉老虎) 
我的帖子也被移过,还有别人的也被移过,CSDN的管理员他们也可以移。
你的帖子是我移的,你向Delphi搬救兵,所以我移到Delphi来了。
呵呵,就此打住吧。不争了,不争了。


    我试了一下,在主线程中先随便操作一下AdoQuery1(比如AdoQuery1.SQL.Text:='...')就能解决你的问题,不过我相信以后还会有其它问题。以下文字你应该见过:Methods and properties of objects in VCL can only be used in a method called using Synchronize.
    其实ADO组件本身支持异步操作的,在ExecuteOptions属性中设置,我没研究过。
    有纪录才能关闭的问题,安装ADO组件补丁(VCL,不是ADO本身)应该就能解决。
2 liulee:
   Ok,就此打住。
加一句
ADOQuery.clear;
ADO是COM组件。在线程中使用时需要先调用CoInitialize,对应的需要调用CoUninitialize。
 CoInitialize  怎么调用,use什么,
我经过反复验证,必须使用Synchronize,其作用是使线程与VCL同步。
VCL的相当一部分代码是线程不安全的,具体的说,大多数由TComponent所派生的类与线程不兼容,会导致一些错误。而Synchronize能解决这个问题,当然效率会低一些。但却是必须的。

备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘