【问题标题】:Managing a COM object in C#在 C# 中管理 COM 对象
【发布时间】:2009-03-24 18:54:31
【问题描述】:

我有一个从 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 中设置此选项的位置

编辑:在 google 群组上找到答案

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); 
    } 
   };

【问题讨论】:

    标签: c# com interop kill


    【解决方案1】:

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

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

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

    更新:

    鉴于 cmets 中的信息,您正在使用 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 会在读取套接字时出错,并且知道也会死。

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

    【讨论】:

    • 我确实控制了源,但我必须在进程外创建它,因为 COM 对象是 32 位的,而我的 C# 主机是 64 位的。
    • 我这里也是人为地创建了挂起行为,但实际代码有时也会挂起,而且项目很大,所以我不能指望其他人做对(遗憾)
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-26
        • 2014-03-16
        • 1970-01-01
        • 1970-01-01
        • 2012-03-05
        • 1970-01-01
        相关资源
        最近更新 更多