请问我用以下的方法去取数据为什么不行呀?
自定义消息:
const
THREAD_GETDATA = WM_USER+1;
THREAD_UPDATEDATA = WM_USER+2;
THREAD_TERMINATE = WM_USER+3;以下是自己定义的多线程类:
TDataThread = class(TThread)
private
FStream: Pointer;
IAppData: IAppServer;
FDelta: OleVariant;
FData: OleVariant;
FcdsData: TClientDataSet; Function GetData(Fcds: TClientDataSet):OleVariant;
Procedure UpdateData(Fcds: TClientDataSet);
protected
Procedure Execute;override;
public
Constructor Create(Fcds: TClientDataSet);
Property Delta: OleVariant read FDelta write FDelta;
Property Data: OleVariant read FData write FData;
end;
constructor TDataThread.Create(Fcds: TClientDataSet);
var
Res: HRESULT;
begin
FreeOnTerminate := True;
OleCheck(CoInitialize(Nil));
Self.FcdsData := Fcds;
try
Res:= CoMarshalInterThreadInterfaceInStream(IID_IAppserver, //用来注册线程。
FcdsData.AppServer,IStream(FStream)); //OleCheck( )AppInteface:=IappServer(IDispatch(DataModule1.skc1.AppServer));
case res of
E_OUTOFMEMORY:
Dialogs.ShowMessage('There was not enough memory to complete the call.');
E_INVALIDARG:
Dialogs.ShowMessage('One or more arguments are invalid. '); //相当于ShowMessage.
end;
except
On e: Exception do
Begin
CoUninitialize;
Dialogs.ShowMessage(E.Message);
exit;
end;
end;
try
Res:= CoGetInterfaceAndReleaseStream(IStream(FStream),IID_IAppServer,IAppData);
case res of
E_INVALIDARG:
Dialogs.ShowMessage('Indicates that input arguments are invalid.');
end;
except
On e: Exception do
Begin
CoUninitialize;
Dialogs.ShowMessage(E.Message);
exit;
end;
end;
Inherited Create(False);
end;procedure TDataThread.Execute;
var
Event: THandle;
Msg: TMsg;
cdsTemp: TClientDataSet;
begin
Event:= Self.Handle;
CoInitialize(Nil);
try
While Not Terminated do
begin
case MsgWaitForMultipleObjects(0,Event,False,INFINITE,QS_ALLINPUT) of
WAIT_OBJECT_0:
begin
While PeekMessage(Msg,0,0,0,PM_REMOVE) do
begin
if Msg.hwnd = 0 Then
begin
Case Msg.message of
THREAD_GETDATA:
begin
cdsTemp:=TClientDataSet(Pointer(Msg.wParam));
Self.Data := Self.GetData(cdsTemp);
end;
THREAD_UPDATEDATA:
begin
cdsTemp:=TClientDataSet(Pointer(Msg.wParam));
Self.UpdateData(cdsTemp);
end;
THREAD_TERMINATE:
Terminate;
end;
end;
end;
end;
end;
end;
finally
CoUnInitialize();
end;
end;function TDataThread.GetData(Fcds: TClientDataSet): OleVariant;
var
ResCount: Integer;
Params: OleVariant;
OwerData: OleVariant;
begin
Result:=IAppData.AS_GetRecords(Fcds.ProviderName,Fcds.PacketRecords,ResCount,1,Fcds.CommandText,Params,OwerData);
end;procedure TDataThread.UpdateData(Fcds: TClientDataSet);
var
iErrCount: Integer;
OwnerData: OleVariant;
begin
IAppData.AS_ApplyUpdates(Fcds.ProviderName,Fcds.Delta,-1,iErrCount,OwnerData);
end;调用:
var
DataThread: TDataThread;我用发送消息的形式:PostThreadMessage(DataThread.ThreadID,THREAD_GETDATA,Integer(Pointer(ClientDataSet1)),0);
来取数据:提老是在SConnect的单元里为提示出一个错误,说什么‘Invalid argument’
自定义消息:
const
THREAD_GETDATA = WM_USER+1;
THREAD_UPDATEDATA = WM_USER+2;
THREAD_TERMINATE = WM_USER+3;以下是自己定义的多线程类:
TDataThread = class(TThread)
private
FStream: Pointer;
IAppData: IAppServer;
FDelta: OleVariant;
FData: OleVariant;
FcdsData: TClientDataSet; Function GetData(Fcds: TClientDataSet):OleVariant;
Procedure UpdateData(Fcds: TClientDataSet);
protected
Procedure Execute;override;
public
Constructor Create(Fcds: TClientDataSet);
Property Delta: OleVariant read FDelta write FDelta;
Property Data: OleVariant read FData write FData;
end;
constructor TDataThread.Create(Fcds: TClientDataSet);
var
Res: HRESULT;
begin
FreeOnTerminate := True;
OleCheck(CoInitialize(Nil));
Self.FcdsData := Fcds;
try
Res:= CoMarshalInterThreadInterfaceInStream(IID_IAppserver, //用来注册线程。
FcdsData.AppServer,IStream(FStream)); //OleCheck( )AppInteface:=IappServer(IDispatch(DataModule1.skc1.AppServer));
case res of
E_OUTOFMEMORY:
Dialogs.ShowMessage('There was not enough memory to complete the call.');
E_INVALIDARG:
Dialogs.ShowMessage('One or more arguments are invalid. '); //相当于ShowMessage.
end;
except
On e: Exception do
Begin
CoUninitialize;
Dialogs.ShowMessage(E.Message);
exit;
end;
end;
try
Res:= CoGetInterfaceAndReleaseStream(IStream(FStream),IID_IAppServer,IAppData);
case res of
E_INVALIDARG:
Dialogs.ShowMessage('Indicates that input arguments are invalid.');
end;
except
On e: Exception do
Begin
CoUninitialize;
Dialogs.ShowMessage(E.Message);
exit;
end;
end;
Inherited Create(False);
end;procedure TDataThread.Execute;
var
Event: THandle;
Msg: TMsg;
cdsTemp: TClientDataSet;
begin
Event:= Self.Handle;
CoInitialize(Nil);
try
While Not Terminated do
begin
case MsgWaitForMultipleObjects(0,Event,False,INFINITE,QS_ALLINPUT) of
WAIT_OBJECT_0:
begin
While PeekMessage(Msg,0,0,0,PM_REMOVE) do
begin
if Msg.hwnd = 0 Then
begin
Case Msg.message of
THREAD_GETDATA:
begin
cdsTemp:=TClientDataSet(Pointer(Msg.wParam));
Self.Data := Self.GetData(cdsTemp);
end;
THREAD_UPDATEDATA:
begin
cdsTemp:=TClientDataSet(Pointer(Msg.wParam));
Self.UpdateData(cdsTemp);
end;
THREAD_TERMINATE:
Terminate;
end;
end;
end;
end;
end;
end;
finally
CoUnInitialize();
end;
end;function TDataThread.GetData(Fcds: TClientDataSet): OleVariant;
var
ResCount: Integer;
Params: OleVariant;
OwerData: OleVariant;
begin
Result:=IAppData.AS_GetRecords(Fcds.ProviderName,Fcds.PacketRecords,ResCount,1,Fcds.CommandText,Params,OwerData);
end;procedure TDataThread.UpdateData(Fcds: TClientDataSet);
var
iErrCount: Integer;
OwnerData: OleVariant;
begin
IAppData.AS_ApplyUpdates(Fcds.ProviderName,Fcds.Delta,-1,iErrCount,OwnerData);
end;调用:
var
DataThread: TDataThread;我用发送消息的形式:PostThreadMessage(DataThread.ThreadID,THREAD_GETDATA,Integer(Pointer(ClientDataSet1)),0);
来取数据:提老是在SConnect的单元里为提示出一个错误,说什么‘Invalid argument’
解决方案 »
- 是否需要ReleaseMutex释放HMutex所有权
- ***********怎么样在程序中访问网上邻居中的共享文件夹(已经知道密码)*************
- 我怎样通过程序检测在系统突然遭断电或非法错误而不正常关闭?
- QUICKREPORT中的QREXPR控件
- 强烈建议斑竹有时间的话,把那些争论语言优劣性,某某语言有没有前途的帖子整理成一个放在最前面,让提问题的人看就行了~
- 程序员身高体重比例,及运动量调查
- 急问:如何设置NMSMTP控件才能让程序连接到SMTP服务器上而不出现要求认证的错误?
- Interface是什么作用, 一个模板?
- 关于 xpmenu 的问题
- 如何将当前音量的大小用TTrackBar表达出来
- 请问金山词霸里输入英文,左边显示框快速的显示出来,请问这是如何实现的呢?好象用到了win api是吗?请给点例子或提点见意。
- RAVE 的图片问题
Res:= CoGetInterfaceAndReleaseStream(IStream(FStream),IID_IAppServer,IAppData);可是,TThread.Create。。只是创建这个线程对象,并不是这个线程的执行。。
你至少应该写在TThread.Execute里面
Res:= CoGetInterfaceAndReleaseStream(IStream(FStream),IID_IAppServer,IAppData);
不是为了线程转接用吗?他不是为了把我们传过去的FCDS的AppServer转接到我们线程类里的IAppData变量里吗?而且如果我把那个私有函数GetData(fcds:TClientDataSet)放到公共接口区,有人为调用就不会有出错,而且能取到数据。
我明白你是想把接口Marshal到工作线程,
可是在TThread.Create...是在调用它的线程。。我猜你这儿是主线程。呵呵。
并不是在你要用接口的那线程
在TThread.Execute才是那线程执行的地方!!!要在这里面MARSHAL才对啊。
而且你的代码有好几个地方调用进入了这个单元。。
你难道不能跟踪到你代码中的一个准确位置吗?另外,‘Invalid argument’这东西是Variant类型检查时候报的异常,
你特别注意检查一下用到变体类型时候。
function TDataBlockInterpreter.LockObject(ID: Integer): IDispatch;
begin
-》 Result := FDispList[ID];
end;
Res:= CoGetInterfaceAndReleaseStream(IStream(FStream),IID_IAppServer,IAppData);
你看这函数的名字,取得接口后就释放STREAM,能让你用第二次吗??
你就不能if not Assigned(IAppData) then
CoGetInterfaceAndReleaseStream.....
很容易发生错误,又难调试
象你的程序客户端就不能用socketConnection来连接
你却用了SocketConnection线程间列集的问题,应该在线程的Execute代码里面coGetInterfaceAndReleaseStream,
而不是在Create方法里面,因为调用Create方法的是主线程象你的问题,完全没有必要Marshal,直接传递一个ServerName和ServerGUID给工作线程
然后由工作线程来创建IAppServer实例再服务主线程就可以了如果多线程概念不是很清晰就不要用COM,或者用COM就避免多线程,
很多时候测试不充分,到用户手上的时候就容易出错
THREAD_GETDATA = WM_USER+1;
THREAD_UPDATEDATA = WM_USER+2;
THREAD_TERMINATE = WM_USER+3;以下是自己定义的多线程类:
TDataThread = class(TThread)
private IAppData: IAppServer;
fHost: string;
fPort: Integer;
fServerGUID: string; Function GetData(Fcds: TClientDataSet):OleVariant;
Procedure UpdateData(Fcds: TClientDataSet);
protected
Procedure Execute;override;
public
constructor TDataThread.Create(
//假设你用的是SocketConnection
const Host: string;
const Port: Integer;
const ServerGUID: string); end;
constructor TDataThread.Create(
//假设你用的是SocketConnection
const Host: string;
const Port: Integer;
const ServerGUID: string);
var
Res: HRESULT;
begin
inherited Create(False);
FreeOnTerminate := True;
fHost := Host; fPort := Port; fServerGUID := ServerGUID;
end;procedure TDataThread.Execute;
var
Event: THandle;
Msg: TMsg;
cdsTemp: TClientDataSet;
begin
//在工作线程内创建一个连接,那就不必marshal了
Event:= Self.Handle;
CoInitialize(nil);
try
SocketConn := TSocketConnection.Create(nil);
try
SocketConn.Host := fHost;
SocketConn.Port := fPort;
SocketConn.ServerGUID := fServerGUID;
SocketConn.Connected := True; //如果连接失败,自己找一个机制反馈给主线程吧
IAppData := SocketConn.GetServer();
if IAppData = nil then
raise Exception.Create('GetServer error'); //如果失败,自己找一个机制反馈给主线程吧
while not Terminated do
begin
case ... of
... //你原来的代码
end;
finally
SocketConn.Destroy();
end;
finally
CoUninitialize();
end;
end;function TDataThread.GetData(Fcds: TClientDataSet): OleVariant;
var
ResCount: Integer;
Params: OleVariant;
OwerData: OleVariant;
begin
Result:=IAppData.AS_GetRecords(Fcds.ProviderName,Fcds.PacketRecords,ResCount,1,Fcds.CommandText,Params,OwerData);
end;procedure TDataThread.UpdateData(Fcds: TClientDataSet);
var
iErrCount: Integer;
OwnerData: OleVariant;
begin
IAppData.AS_ApplyUpdates(Fcds.ProviderName,Fcds.Delta,-1,iErrCount,OwnerData);
end;我也是菜鸟一个,所以你只能参考,如果不行也别骂我
另外,没功劳也有苦劳,给分的时候,请适当给点