▁▂▃▄▅▆▇ 线程中使用TClientDataSet的可能性有吗???▇▆▅▄▃▂▁
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!!!!!
问题点数:300、回复次数:18Top
1 楼Crob(Take Everything Easy!)回复于 2001-11-02 20:42:02 得分 0
upupTop
2 楼cobi(我是小新)回复于 2001-11-02 20:50:47 得分 0
XXXX指的是什么?
我想线程中是应该可以用clientdataset的,而且你现在的问题也不一顶是它的原因Top
3 楼Crob(Take Everything Easy!)回复于 2001-11-02 21:07:09 得分 0
XXXX = Variant,具体错误没记下来
肯定是线程的问题,你不用怀疑了.
我在主线程中调用Execute是可以正常执行的.
有些控件是不支持线程安全的, 我只是想知道有没有可能在线程中使用TClientDataSet.Top
4 楼Crob(Take Everything Easy!)回复于 2001-11-02 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 2000Top
5 楼xzm2000(傻B)回复于 2001-11-02 21:26:41 得分 0
看看tclientdataset的fetchondemand是否为trueTop
6 楼Miracle(新一代的开山怪)回复于 2001-11-02 21:47:19 得分 0
应该可以把,我还没试过,估计可能需要调用CoInitialize()Top
7 楼Miracle(新一代的开山怪)回复于 2001-11-02 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.
Top
8 楼Crob(Take Everything Easy!)回复于 2001-11-03 10:00:30 得分 0
我试试
如果成功决不失言Top
9 楼Crob(Take Everything Easy!)回复于 2001-11-03 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;Top
10 楼Crob(Take Everything Easy!)回复于 2001-11-03 17:05:08 得分 0
faint~~~~~~~~~~~~~Top
11 楼Miracle(新一代的开山怪)回复于 2001-11-03 17:16:34 得分 0
呵呵,我一般不这样用。因为多数Delphi所创建的MIDAS服务器都是STA(Single-Threaded Apartment)的,每个Apartment只能有一个线程进入,而且中途不允许换人,你这样在多线程中呼唤STA服务器当然无法正确执行。除非你做到在同一个线程中初始化服务器连接-转换服务器接口等一些列操作,或者自己手工编写线程间的转换(Marshaling)代码,又或者把服务器写成MTA,否则注定无法成功的。Top
12 楼Miracle(新一代的开山怪)回复于 2001-11-03 17:18:34 得分 0
还有,你上面的例子,好像没有设置RemoteServer和Provider,是为了示意而省略了?
FreeOnTerminate:=true;
fCDS:=TClientDataset.Create(nil);
try
with FCDS do
begin
Close();
CommandText := 'SELECT * FROM .....';
Open(); //线程中执行这里会出错
end;
finally
fCDS.Free;
end; Top
13 楼Miracle(新一代的开山怪)回复于 2001-11-03 17:20:41 得分 0
又及,使用ClientDataset会调用Midas.dll中的服务,也就是说使用了COM,所以在独立线程中处理ClientDataset时,最好使用CoInitialize。Top
14 楼Crob(Take Everything Easy!)回复于 2001-11-03 17:32:12 得分 0
我是省略了
我还试过将SocketConnection也封装在线程类中, 但还是一样.
看来是没办法了
我会给分的Top
15 楼Miracle(新一代的开山怪)回复于 2001-11-03 17:36:09 得分 0
呵呵,因为以前很少来CSDN,我现在一共才171分,如果你给我300,我可真是发了……Top
16 楼Crob(Take Everything Easy!)回复于 2001-11-03 17:45:44 得分 0
我分多得很
难得问一次问题的
马上给分
我的QQ:2850178Top
17 楼halfdream(哈欠)回复于 2001-12-02 19:26:11 得分 0
TO :CROB
>>'''ClientDataSet并没用到Ole接口
不会吧.你自己看源码,ClientDataSet是离不开COM 接口的.
关于类似的问题, 其实早有贴子已经讨论得比较成熟了.
可以参见
http://www.csdn.net/expert/topic/177/177973.shtm
Top
18 楼halfdream(哈欠)回复于 2001-12-02 19:33:42 得分 0
在线程创建CONNECTION连接(socket或DCOM)是必须的.
超过一个线程,
CoInitializeEx 不是最好要用..而是必须要用.
Top




