当前位置:主页>销售管理软件> 列表

请问一个很烦也很无奈的问题,有时候clientdatase 找最好的家庭记账软件

财务软件版1楼: 我的线程如下,即使把ClientDataset的open过程在进程中打开也会出现有时候在open处停止响应的问题,请大侠们指点指点吧!

unit UQueryThread;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
npublicMisc,npublicStrAndTstr,npublicFileAndDir,npublicSQLStr,npublicDBVcl,
npublicTstrSection,npublicTreeview,npublicNonDBVcl,dbclient,UShowInfo,
db,dbtables,dbgrids,UTsystbl0,UTsystbl1,UTsystbl2p1,SConnect;

type
TQueryThread = class(TThread)
private
public
Fsoc: TSocketConnection;
FCDS:TClientDataSet;
Running:boolean;
constructor Create(CDS1:TClientDataSet;soc: TSocketConnection;SQL:string);
destructor Destroy; override;
protected
procedure Execute;override;

end;

implementation

{ TQueryThread }

constructor TQueryThread.Create(CDS1:TClientDataSet;soc: TSocketConnection;SQL:string);
begin
FreeOnTerminate:=false;

Fsoc:=TSocketConnection.Create(application);
FSoc.Address:=soc.Address;
FSoc.Host:=soc.Host;
FSoc.Port:=soc.Port;
FSoc.ServerName:=soc.ServerName;
Fsoc.ServerGUID:=soc.ServerGUID;

FCDS:=TClientDataSet.Create(application);
FCDS.RemoteServer:=Fsoc;
FCDS.CommandText:=SQL;
FCDS.PacketRecords:=CDS1.PacketRecords;
FCDS.ProviderName:=CDS1.ProviderName;

inherited Create(true);
end;

destructor TQueryThread.Destroy;
begin
FSOC.Connected:=false;
FCDS.Close;
FreeAndNil(FCDS);
FreeAndNil(FSOC);
inherited;
end;

procedure TQueryThread.Execute;
begin
Running:=true;
try
Fsoc.Connected:=true;

FCDS.Open;//有时候到这里就不继续往下做了,程序也失去响应了,要强行关闭才行

Running:=false;
finally

end;

end;

end.

2楼: Fsoc.Connected:=true;

FCDS.Open;//有时候到这里就不继续往下做了,程序也失去响应了,要强行关闭才行

将 Fsoc.Connected:=true; 去掉试试看,一般来说Open的时候,会自动打开连接了,先打开了再OPEN,好像是会创建新的连接,然后会导致错误。 
试试看,不知道对不对。 如东莞进销存

3楼: Fsoc:=TSocketConnection.Create(application);
Application对象不是线程安全的,不要在线程里面(或者线程内部创建的对象中)引用任何外部的VCL对象,VCL的框架本身就不是线程安全的。

不过这个可能和你的open时停止响应无关,我仅是指出这一点提醒您注意而已。

4楼: 把程序中的
Fsoc:=TSocketConnection.Create(application);
改为
Fsoc:=TSocketConnection.Create(nil);

和把
Fsoc.Connected:=true;去掉还是一样啊,该怎么办呢?

5楼: 可能是远程主机没有响应,你把FSoc指向本机试试,通过了再试远程。

6楼: TO nicai_wgl
在本机调试没有出现过这种错误,就是在远程调试的时候才发现这种错误,请问有什么可能会造成这种错误呢?还发现,在远程调试时(在delphi中按F9运行)未出现错误,但直接运行EXE就会不定时出现这种错误。

财务软件版7楼: 呵呵,如果F9不出错而直接运行出错,可能是网络延时,在
Fsoc.Connected:=true;
sleep(1000); //加延时试试
FCDS.Open;//有时候到这里就不继续往下做了,程序也失去响应了,要强行关闭才行

8楼: 能不能在调用线程时用 WaitForSingleObject(t1.Handle,10) 循环来检测是否在open处停顿呢?但好像用


WaitForSingleObject(t1.Handle,10);
或者用if WaitForSingleObject(t1.Handle,10)=WAIT_TIMEOUT then

或者用if WaitForSingleObject(t1.Handle,10)=WAIT_OBJECT_0 then

都在open时就同时停顿不能执行下去,要怎样才能检测到停顿呢?

9楼: 现在问题变成了怎样检测长时间open不响应时,如何抛出异常信息了

10楼: 在进程或线程中能够处理都行啊,如果分不够,还可以再加200分啊

11楼: 可以用TSimpleEvent, 在Open之前ResetEvent, Open成功后SetEvent, 在主线程中等待,
如果超时则弹出异常, 结束子线程。

12楼: 程序改成了下面
unit UQueryThread;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
dbclient,db,dbtables,dbgrids,SConnect,SyncObjs;

type
TQueryThread = class(TThread)
private
public
Fsoc: TSocketConnection;
FCDS:TClientDataSet;
SimpEvent:TSimpleEvent;
constructor Create(CDS1:TClientDataSet;soc: TSocketConnection;SQL:string);
destructor Destroy; override;
protected
procedure Execute;override;



end;

implementation

{ TQueryThread }

constructor TQueryThread.Create(CDS1:TClientDataSet;soc: TSocketConnection;SQL:string);
begin
inherited Create(true);
self.FreeOnTerminate:=false;

Fsoc:=TSocketConnection.Create(nil);
FSoc.Address:=soc.Address;
FSoc.Host:=soc.Host;
FSoc.Port:=soc.Port;
FSoc.ServerName:=soc.ServerName;
Fsoc.ServerGUID:=soc.ServerGUID;

FCDS:=TClientDataSet.Create(nil);
FCDS.RemoteServer:=Fsoc;
FCDS.CommandText:=SQL;
FCDS.PacketRecords:=CDS1.PacketRecords;
FCDS.ProviderName:=''tmpQryProvider'';

end;

destructor TQueryThread.Destroy;
begin
FreeAndNil(SimpEvent);
FSOC.Connected:=false;
FCDS.Close;
FreeAndNil(FCDS);
FreeAndNil(FSOC);
inherited;
end;

procedure TQueryThread.Execute;
begin
try
SimpEvent:=TSimpleEvent.Create;
SimpEvent.ResetEvent;
FCDS.Active:=true;
SimpEvent.SetEvent;
finally
end;
end;

end.

然后是调用的代码:
t1:=TQueryThread.Create(cltDataSet,DCOM1,sql);
t1.resume;
while t1.SimpEvent=nil do
sleep(1);

if WaitForSingleObject(t1.SimpEvent.Handle,5000)=WAIT_TIMEOUT then
t1.Suspend;

if t1.FCDS.Active then
begin
cltdataset.Data:=t1.FCDS.Data;
result:=true;
end
else
begin
application.MessageBox(''数据搜索失败'',''提示'',0);
while t1.Suspended=false do
t1.Suspend;
end;


结果还是一样,如果在FCDS.Active:=true;处死掉还是不会执行t1.suspend;这句 如最好的家庭记账软件

13楼: 其实你没有必要在线程里面开多一个连接,还是用原来的连接吧。
具体的实现你可以看看这个帖子。
http://www.delphibbs.com/delphibbs/dispq.asp?lid=2280814
首先你应该在创建线程的时候把取数据时候需要调用的接口传递进来。
OleCheck(CoMarshalInterThreadInterfaceInStream(IID_IAppServer,FCDS.AppServer,
IStream(FStream)));
然后你在调用该接口的时候需要把它拿回来。
OleCheck(CoGetInterfaceAndReleaseStream(IStream(FStream), IID_IAppServer,
Appserver));
好了,可以调用该接口拿数据了。
FNewData :=AppServer.AS_GetRecords (FCDS.ProviderName,
-1,RecsOut,MetaDataOption,'''',Params,OwnerData);
然后把数据更新回去,因为要接受数据的是一个线程外部的对象,你需要跟主线程同步
Synchronize(UpdateCDS);
这样就完成了。

财务软件版14楼: To:kkkchenA
这种方法在我的系统不能用。

系统换了N种方法后问题好像解决了

15楼: 多人接受答案了。