2

我有一个从 C# 调用的 ATL COM exe。我将引用导入到 C# 中,一切正常,生成了 exe,我可以在其上调用函数。现在,我实例化了其中几个 COM 对象。偶尔其中一个会挂起。释放 COM 对象没有任何作用,因为它仍在运行。我无法终止该过程,因为然后我会丢失所有其他表现良好的对象。所以,

  1. 有没有办法真正杀死一个人?
  2. 有没有办法为每个请求的 com 对象启动一个 exe?
  3. 如果我的客户端意外退出,COM exe 永远不会被清理。有没有什么办法解决这一问题?

理想情况下,我将能够为每个对象实例启动一个 COM exe,并能够对其进行 Process.Kill()。是否可以选择其中任何一个?下面是我用来创建对象的类,在这种情况下,RandomID()(人为地)需要很长时间才能返回。另外,如果有办法用另一种语言做到这一点,我也愿意尝试一下。谢谢。

public class MyComObject:IDisposable
{
    private bool disposed = false;
    MyMath test;

    public MyComObject()
    {
        test = new MyMath();
    }

    public double GetRandomID()
    {
        if (test != null)
            return test.RandomID();
        else
            return -1;
    }

    public void Dispose()
    {
        Dispose(true);

        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (test != null)
                Marshal.ReleaseComObject(test);

            disposing = true;
        }
    }
}

编辑:看起来如果我可以将其设置为“单次使用”,一切都会按我的意愿工作。但是,我找不到在 VS 2008 中设置此选项的位置

编辑:在谷歌群组上找到答案

class CMathServerModule : public CAtlExeModuleT< CMathServerModule >
   {

    public :
   DECLARE_LIBID(LIBID_MathServerLib)
   DECLARE_REGISTRY_APPID_RESOURCEID(IDR_MATHSERVER, "{2FA977F0-050C-4010-A09F-4FE6D75F3024}")
   HRESULT RegisterClassObjects(DWORD dwClsContext, DWORD dwFlags) 
   throw() 
    { 
        dwFlags = ((dwFlags & ~(REGCLS_MULTIPLEUSE | REGCLS_MULTI_SEPARATE )) | 
                REGCLS_SINGLEUSE); 
        return CAtlExeModuleT<CMathServerModule>::RegisterClassObjects(dwClsContext, dwFlags); 
    } 
   };
4

3 回答 3

2

当对象挂起时会发生什么?即你怎么知道它挂了?

它可能挂起的原因有很多,但其中一个是系统中某处的线程已初始化 COM,但未发送 Windows 消息。

你控制 COM 服务器 exe 的源代码吗?它作为 DLL 服务器可能要简单得多,因此您可以在进程中加载​​它,而这些问题都不存在。

更新:

鉴于评论中的信息,您正在使用 COM exe-remoting 来解决 32/64 位 thunking 的问题。

我对 COM exe 服务器的体验非常糟糕。COM DLL 是非常简单的东西,COM exe 是非常复杂且不可靠的东西。它们可以正常工作 - 只是 - 在一些交互式 GUI 场景中。

但是你可能会更好地推出自己的 IPC 机制,这听起来很奇怪。其实没那么难。假设 64.exe 创建了一个监听套接字,它还维护了一个 32.exe 进程的句柄,按需创建它。它可以随心所欲地创造尽可能多的或尽可能少的,并随心所欲地杀死它们。当 32.exe 启动时,它会连接到套接字并读取它——这就是它开始工作的方式。64.exe 通过接受的套接字连接发送指令,它与相应的进程句柄一起存储。

这样做的好处是,如果 64.exe 突然死掉,32.exe 会在读取套接字时出错,并且知道也会死掉。

您通过套接字发送的内容的格式可以非常简单。计数缓冲区是理想的(发送长度,然后是那么多字节的数据)。

于 2009-03-24T19:00:55.600 回答
1

我不知道这是否是答案,但您的 Dispose 方法中的代码将 disposing 设置为 true,而不是 dispose。它允许多次调用 ReleaseComObject。

我会设置为true,然后看看你是否有同样的问题。

于 2009-03-24T19:42:47.293 回答
0

我开发了一些服务导出 COM 接口并且没有问题,这是在服务器池中运行的。
我的建议是尝试使用 WinDbg 监控您的应用程序,编译包含调试信息的代码并一起安装 pdb 文件。

于 2009-03-26T21:46:01.693 回答