【问题标题】:Controlling the Threading Model of COM objects served by .NET Out of Process Servers控制由 .NET 进程外服务器提供的 COM 对象的线程模型
【发布时间】:2010-10-11 19:42:12
【问题描述】:

在使用 C# 创建进程外 COM 服务器时,如 Microsoft 的 All-In-One 代码示例中所述:CSExeCOMServer,似乎很难控制在服务器中创建的对象的线程模型(由客户)。

正在创建的对象需要在 STA 中,因为它使用 WPF 对象,并且它的工厂正在注册,如 ExeCOMServer.cs 的第 95 行所示并粘贴在下面...

private void PreMessageLoop()
{
    //
    // Register the COM class factories.
    // 

    Guid clsidSimpleObj = new Guid(SimpleObject.ClassId);

    // Register the SimpleObject class object
    int hResult = COMNative.CoRegisterClassObject(
        ref clsidSimpleObj,                 // CLSID to be registered
        new SimpleObjectClassFactory(),     // Class factory
        CLSCTX.LOCAL_SERVER,                // Context to run
        REGCLS.MULTIPLEUSE | REGCLS.SUSPENDED,
        out _cookieSimpleObj);
    if (hResult != 0)
    {
        throw new ApplicationException(
        "CoRegisterClassObject failed w/err 0x" + hResult.ToString("X"));
    }

但是,CreateInstance 函数总是在 MTA 中的新线程中调用。本地服务器的主线程被标记(并验证)为 STA 线程似乎并不重要。

所有已发现的有关此事的材料都表明,所创建对象的单元应与工厂注册所在线程的单元相匹配。事实上,这似乎是使用 ATL COM 服务器(与托管 C++ 混合创建对象)时的情况,但这种方法似乎是将一个新线程注入到初始化参数的工作流中,特别是 COM 线程模型, 似乎不可更改。

有没有人在不求助于主要用非托管代码编写的 COM 服务器的情况下解决了这个问题。

【问题讨论】:

  • 呃,我讨厌他们想出的废话。当他们在中国被录用时,我与 MSDN 论坛密切相关。那时我是一个社区模组。该库根本没有经过同行评审,它跨越了“55% 准确”的角度。尤其是那个叫“哥”的家伙,对于他的无知,是非常危险的。服务器的线程模型受服务器如何初始化 COM 的影响。不是客户。
  • 感谢您的洞察力...但是该示例似乎可以很好地完成它的工作。让 MTA 初始化我们的对象在技术上并不是不正确的。令人困惑的部分是 SERVER 的主线程属于一个 STA,但框架(COM、OLE 等)在服务器中创建了一个新线程,该线程位于服务器的 MTA 中,以调用我们工厂的 CreateInstance。

标签: .net com localserver


【解决方案1】:

我们最近在设置 WinForm 应用程序来托管一些 64 位互操作的对象时遇到了非常相似的情况。 UI 线程在启动时进入 STA(使用 STAThread 属性)。不久之后,我们发现所有构造函数都在 UI 线程 (STA) 中运行,但所有其他方法都在 .Net 创建的工作线程 (MTA) 中运行。

问题并不是真正的 MTA,但我们确实有访问 UI 的方法,而且它们总是在困扰我们的工作线程中运行。虽然我们不知道如何强制 .Net 编组对 UI 线程 (STA) 的调用,但我们确实想出了一些非常肮脏的技巧,涉及 ContextBoundObject 和方法拦截。我不会详细介绍,但您可以查看 System.Runtime.Remoting.Messaging 和 System.Runtime.Remoting.Contexts 命名空间。这个想法是欺骗 CCW 将透明代理视为互操作对象,我们拦截对代理的每个调用,将消息传递给 UI 线程,然后将消息反向转换为方法调用。肮脏的?是的。表现?很坏。但它有效。

如果您想查看方法拦截代码,可以给我发电子邮件。

【讨论】:

    猜你喜欢
    • 2014-02-18
    • 2011-07-19
    • 2010-10-04
    • 2019-11-06
    • 2013-01-20
    • 2012-09-06
    • 1970-01-01
    • 2011-11-05
    • 2011-05-17
    相关资源
    最近更新 更多