首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ Builder >

调用DLL实现DCOM连接后,程序结束正常结束但不能从内存退出,该怎么处理

2012-03-16 
调用DLL实现DCOM连接后,程序结束正常结束但不能从内存退出1)编写DLL通过DCOM实现数据存储,查询。主程序采用

调用DLL实现DCOM连接后,程序结束正常结束但不能从内存退出
1)编写DLL通过DCOM实现数据存储,查询。主程序采用静态调用方式,函数工作正常,但主程序正常关闭后,主程序不能从内存里退出。
2)DLL里面有多个输出函数需要用到数据模块Tdm_StoredData,频繁调用这个dll是否需要考虑数据模块冲突的问题?
3)DLL调用数据模块中的CDS组件获得查询结果,如何将结果传递到调用主程序,现在使用的是动态数组,有没有更好解决方法?
4)如何实现大块数据在DCOM间传递,那样就可以把这些代码放到DCOM中实现?

C/C++ code
//dll入口int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved){        switch(reason)           {                  case   DLL_PROCESS_ATTACH:            HRESULT coret = CoInitialize(NULL);                if(coret ! = S_OK && coret != S_FALSE)                        {                            //异常                        }                        else                        {                            dm_StoredData =new Tdm_StoredData(NULL);                        }                        break;                  case   DLL_PROCESS_DETACH:                        if(dm_StoredData !=NULL)                        {                                delete dm_StoredData;                        }                        CoUninitialize();                             break;                  case DLL_THREAD_ATTACH: break;                  case DLL_THREAD_DETACH: break;                  default:                  break;}//变量定义typedef struct{    AnsiString         SID;                 //....}SAT, pSAT;typedef DynamicArray<SAT>  ASAT;//函数extern "C" __declspec(dllexport)__stdcall  int Sat_Add(ASAT &asat){    AnsiString CMDSQL;    int nReturnVal = -1;    AnsiString satData;    int x=0;    CMDSQL = "USE cs select * from work ";    try    {        try{            dm_StoredData->cds->Active = false;            dm_StoredData->cds->CommandText = CMDSQL;            dm_StoredData->cds->Active = true;            if(dm_StoredData->cds->RecordCount)            {                asat.Length = dm_StoredData->cds->RecordCount;                                while(!dm_StoredData->cds->Eof)                {                    asat[x].SatID = dm_StoredData->cds->FieldByName("id")->AsString;                    //...                    x++                    dm_StoredData->cds->Next();                }            }            dm_StoredData->cds->Active = false;        }        catch(Exception &E)        {            //ShowMessage(E.Message);        }    }    __finally    {        dm_StoredData->cds->Active = false;    }    return nReturnVal;}


[解决办法]
看看下面这代码对楼主有没啥助益(几年前为VB当中做远程调用写的,可能代码看起来会有些许别扭,将就着看吧)
C/C++ code
// EASYDCOMOBJECTIMPL.H : Declaration of the TEasyDCOMObjectImpl#ifndef EasyDCOMObjectImplH#define EasyDCOMObjectImplH#define ATL_APARTMENT_THREADED#include "EasyDCOMObject_TLB.h"#include "SConnect.hpp"#include "MConnect.hpp"/////////////////////////////////////////////////////////////////////////////// TEasyDCOMObjectImpl     Implements IEasyDCOMObject, default interface of EasyDCOMObject// ThreadingModel : Apartment// Dual Interface : TRUE// Event Support  : FALSE// Default ProgID : Project1.EasyDCOMObject// Description    : /////////////////////////////////////////////////////////////////////////////class ATL_NO_VTABLE TEasyDCOMObjectImpl :  public CComObjectRootEx<CComSingleThreadModel>,  public CComCoClass<TEasyDCOMObjectImpl, &CLSID_EasyDCOMObject>,  public IDispatchImpl<IEasyDCOMObject, &IID_IEasyDCOMObject, &LIBID_EasyDCOMObject>{private:   int Port;   TInvokeType InvokeType;   char MethodName;   char ComputerName[MAX_COMPUTERNAME_LENGTH + 1];public:  TSocketConnection *SocketServer;  TWebConnection *WebServer;  TDCOMConnection *DCOMServer;  TEasyDCOMObjectImpl()  {     SocketServer=new TSocketConnection(NULL);     WebServer=new TWebConnection(NULL);     DCOMServer=new TDCOMConnection(NULL);     ZeroMemory(ComputerName,MAX_COMPUTERNAME_LENGTH + 1);     DWORD dNameLen=MAX_COMPUTERNAME_LENGTH + 1;     GetComputerName(ComputerName,&dNameLen);     InvokeType=eoiSocketInvoke;     Port=SocketServer->Port;  }  ~TEasyDCOMObjectImpl()  {     SocketServer->Free();     WebServer->Free();     DCOMServer->Free();  }  // Data used when registering Object   //  DECLARE_THREADING_MODEL(otApartment);  DECLARE_PROGID("EasyDCOMObject.EasyDCOMObject");  DECLARE_DESCRIPTION("");  // Function invoked to (un)register object  //  static HRESULT WINAPI UpdateRegistry(BOOL bRegister)  {    TTypedComServerRegistrarT<TEasyDCOMObjectImpl>     regObj(GetObjectCLSID(), GetProgID(), GetDescription());    return regObj.UpdateRegistry(bRegister);  }BEGIN_COM_MAP(TEasyDCOMObjectImpl)  COM_INTERFACE_ENTRY(IEasyDCOMObject)  COM_INTERFACE_ENTRY2(IDispatch, IEasyDCOMObject)END_COM_MAP()// IEasyDCOMObjectpublic:   STDMETHOD(GetName(BSTR* S));  STDMETHOD(set_Port(const int Value));  STDMETHOD(get_Port(int* Value));  STDMETHOD(set_InvokeType(const TInvokeType Value));  STDMETHOD(get_InvokeType(TInvokeType* Value));  STDMETHOD(GetObj(const BSTR PROGID,const BSTR SERVER,IDispatch ** iObj));};#endif //EasyDCOMObjectImplH 


[解决办法]
由于水平有限.楼主的问题出在哪我不知道.

但总感觉有些得不偿失.

即然用到了RDM. 为什么还要按普通的DLL的方式来写代码.

2)DLL里面有多个输出函数需要用到数据模块Tdm_StoredData,频繁调用这个dll是否需要考虑数据模块冲突的问题?

为什么不用TDCOMConnection. TSocketConnection ...的AppServer接口.还要自己导出一堆函数.

3)DLL调用数据模块中的CDS组件获得查询结果,如何将结果传递到调用主程序,现在使用的是动态数组,有没有更好解决方法?

RDM上的TDataSetProvider的DataSet属性指向ADOQuery/ADOxxxx. 当ADOQurery/ADOxxxx打开的时候. 直接返回TDatasetProvider的Data属性就行了.

4)如何实现大块数据在DCOM间传递,那样就可以把这些代码放到DCOM中实现? 
大块有多大, 如果在同一台机器上. 一般情况下不切成小块也可以. 先试试看为好.

热点排行