▁▂▃▄▅▆▇ 线程中使用TClientDataSet的可能性有吗???▇▆▅▄▃▂▁一个在没搞定的问题(300分)

  • 主题发起人 主题发起人 crob
  • 开始时间 开始时间
C

crob

Unregistered / Unconfirmed
GUEST, unregistred user!
发表时间:2001-11-2 20:25:53


TClientDataSet通过Midas连接远端数据模块,由于数据处理量大,我考虑将一部分数据处理工作另外开一个线程,这样就不会影响到主线程的工作了.

我自己做了TThread继承的线程类,在类中定义TClientDataSet.
线程如果单独执行会报出类"XXXX不是一个数组的错误". 但我如果我在主线程中执行TThread.Execute完全可以运行

TChkThread = class(TThread)
m_bChkId: boolean;
mDays: integer;
mhandle: integer;
sConn: TSocketConnection;
cds_tmp : TClientDataSet;
//cds_tmp会在Create中初始化并连接成功
constructor Create(days: integer; bId: boolean);
procedure Execute; override;
destructor Destroy; override;
procedure chkcustid(); //我的处理函数,在Execute中执行
procedure chkmDays(days: integer);
end;

这可能是VCL的缺陷,但我还是想知道可不可以在线程中使用TClientDataSet.

300分,如果解决再给300!!!!!



回复贴子:
回复人: Crob(干净的袜子) (2001-11-2 20:42:03) 得0分
upup
回复人: cobi(我是小新,我只有5岁) (2001-11-2 20:50:48) 得0分
XXXX指的是什么?
我想线程中是应该可以用clientdataset的,而且你现在的问题也不一顶是它的原因
回复人: Crob(干净的袜子) (2001-11-2 21:07:09) 得0分
XXXX = Variant,具体错误没记下来

肯定是线程的问题,你不用怀疑了.
我在主线程中调用Execute是可以正常执行的.

有些控件是不支持线程安全的, 我只是想知道有没有可能在线程中使用TClientDataSet.
回复人: Crob(干净的袜子) (2001-11-2 21:11:34) 得0分
具体错误是

Project xxx.exe raised exception class EAccessViolation with message' Access violation at address .................Write of address 0000030. Process stoped Use step or .....

很常见的错误提示,另外我连接的是SQL server 2000
回复人: xzm2000(不不)(每天都要进步) (2001-11-2 21:26:41) 得0分
看看tclientdataset的fetchondemand是否为true
回复人: Miracle() (2001-11-2 21:47:20) 得0分
应该可以把,我还没试过,估计可能需要调用CoInitialize()
回复人: Miracle() (2001-11-2 21:57:48) 得300分
我写了如下代码进行测试,没有发生任何问题。
unit Unit2;

interface

uses
Classes, DBClient;

type
TrdABC = class(TThread)
private
{ Private declarations }
fCDS:TClientDataset;
protected
procedure Execute; override;
end;

implementation
uses
ActiveX, 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 TrdABC.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }

{ TrdABC }


procedure TrdABC.Execute;
begin
FreeOnTerminate:=true;
CoInitialize(nil);
try
fCDS:=TClientDataset.Create(nil);
try
with FCDS.FieldDefs.AddFieldDef do
begin
DataType:=ftInteger;
Name:='ID';
end;
fCDS.CreateDataSet;
{ Place thread code here }
finally
fCDS.Free;
end;
finally
CoUnInitialize;
end;
end;

end.

回复人: Crob(干净的袜子) (2001-11-3 10:00:30) 得0分
我试试

如果成功决不失言
回复人: Crob(干净的袜子) (2001-11-3 11:14:01) 得0分
to Miracle()

看了你的例子, 发现对我没什么用, 因为你只是在线程中建立了本地的数据集
而我是要从无端数据源取数据集,不用CoInitialize也可以,ClientDataSet并没用到Ole接口 , 我想不用初始化的.

我的程序中也可以线程中操作本地数据集, 但不能在线程中发送CommandText到服务器.

我要求的是
procedure TrdABC.Execute;
begin
FreeOnTerminate:=true;
fCDS:=TClientDataset.Create(nil);
try
with FCDS do
begin
Close();
CommandText := 'SELECT * FROM .....';
Open(); //线程中执行这里会出错
end;
finally
fCDS.Free;
end;
回复人: Crob(干净的袜子) (2001-11-3 17:05:09) 得0分
faint~~~~~~~~~~~~~
回复人: Miracle() (2001-11-3 17:16:35) 得0分
呵呵,我一般不这样用。因为多数Delphi所创建的MIDAS服务器都是STA(Single-Threaded Apartment)的,每个Apartment只能有一个线程进入,而且中途不允许换人,你这样在多线程中呼唤STA服务器当然无法正确执行。除非你做到在同一个线程中初始化服务器连接-转换服务器接口等一些列操作,或者自己手工编写线程间的转换(Marshaling)代码,又或者把服务器写成MTA,否则注定无法成功的。
回复人: Miracle() (2001-11-3 17:18:35) 得0分
还有,你上面的例子,好像没有设置RemoteServer和Provider,是为了示意而省略了?
FreeOnTerminate:=true;
fCDS:=TClientDataset.Create(nil);
try
with FCDS do
begin
Close();
CommandText := 'SELECT * FROM .....';
Open(); //线程中执行这里会出错
end;
finally
fCDS.Free;
end;
回复人: Miracle() (2001-11-3 17:20:42) 得0分
又及,使用ClientDataset会调用Midas.dll中的服务,也就是说使用了COM,所以在独立线程中处理ClientDataset时,最好使用CoInitialize。
回复人: Crob(干净的袜子) (2001-11-3 17:32:13) 得0分
我是省略了

我还试过将SocketConnection也封装在线程类中, 但还是一样.
看来是没办法了

我会给分的
 
我KAO
有必要这么麻烦吗?
你有没有听说过ADO的异步存取方式?
或是少量多次从中间件取得数据的方式?
看看李维的书,可能有帮助。
 
对你程序受影响的只是在ClientDataSet1.Open时,如果你从远
端数据模块提取大量的数据到本地,可以想别的办法!又不影响你的主程序的运行。
 
后退
顶部