【问题标题】:STA or MTA for indirectly used COM ObjectsSTA 或 MTA 用于间接使用的 COM 对象
【发布时间】:2015-03-03 04:55:39
【问题描述】:

我想我了解公寓的概念以及为什么使用 STA 或 MTA,但是一个问题 想出了到目前为止我没有找到解决方案。

如果我的应用程序在后台使用 COM 对象,例如来自第三个 派对库,我怎么知道我是否可以使用 MultiThreaded-Appartment (MTA)? 在那种情况下,我不知道这些对象是否是线程安全的,所以我需要去 使用 STA,只是为了安全起见?

【问题讨论】:

    标签: com sta mta


    【解决方案1】:

    您能否在 STA 或 MTA 线程代码上使用某些 COM 接口指针取决于您是否在该线程上获得该指针。如果您可以在 STA(或 MTA)线程上获得要点 - 您最好进一步使用它,前提是您不直接将其传递给另一个公寓。

    如果 COM 服务器以某种方式注册,由于单元类型不匹配而您无法获取指针(典型情况:STA 线程和 COM 服务器使用“免费”单元模型注册),那么 COM 将尝试为您编组指针.如果封送成功,您的代码会收到指针,您可以从那里开始。否则你会得到一个错误,并且你尝试从另一个公寓做同样的事情会成功。基本上,这是获得能够在 STA 或 MTA 线程上使用特定 COM 接口的答案的唯一可靠的通用方法。

    在更具体的实例化 COM 对象的情况下,您可以查看其注册表信息以查看实例化是否与您的公寓类型匹配。在任何情况下,进程外服务器都会通过编组为您提供 COM 接口指针,因此任何客户端单元都可以使用该服务器。

    不存在服务器对象是否是线程安全的问题。如果他们的 COM 注册正确(尤其是 STA 进程内服务器没有宣布 Free/Both 注册)并且编组可用,则免费包含线程安全。

    【讨论】:

    • 谢谢!我不明白每一点,因为我对 COM 相关的东西并不深入。我根本没有使用任何 COM 对象,但有些代码似乎在后台使用了 COM。例如,我得到了一个阻塞的终结器,因为 vb.net 使用 STA 作为默认值,并且消息循环被 thread.Sleep 阻塞。我想确保,我可以安全地切换到 MTA(这是 c# 中的默认设置),之后不再关心它;)。但是经过大量调查,我仍然不确定这是否会以某种方式破坏我的代码!?
    • COM 的规则是你不要在公寓之间直接传递指针(这通常意味着在 STA 线程中你不能在这个线程之外获取指针,你可以在 MTA 线程之间传递指针但不能在外部进入 STA 线程)。当您处理来自 VB.NET 代码的 COM 接口时,您需要牢记这一点。 .NET 运行时会进行额外的检查并防止滥用指针,因此任何一步都可能导致异常。
    【解决方案2】:

    根据ThreadingModel 字段,已注册的 COM 对象将属于一个公寓(another article 是关于具有更大、可能更简单的表的 COM 公寓)。

    基本上,ThreadingModel 告诉新创建的对象将属于哪个单元:

    • 未指定

      主 STA(第一个 CoInitialized STA;如果不存在,则 COM 创建一个,称为主机 STA)

    • 公寓

      一个 STA(如果我们在一个 STA 中,就是它,否则就是主机 STA)

    • 免费

      一个 MTA(如果我们在 MTA 中,就是它;否则,COM 创建它,称为主机 MTA)

    • 两者

      现在的公寓是什么

    • 中性

      中性公寓

    如果您可能正在使用 MTA 对象并且您怀疑它们是否是“线程安全的”(这通常意味着它将在每个方法/属性调用上使用实例级锁定),那么您真的无能为力它。例如,您可以让多个 STA 同时访问同一个 MTA 对象。

    一个 STA 调用并不一定会给您这种线程安全性,除非您保证没有其他 STA 并且没有其他人在使用相同的对象。

    “保证”则相反:一个 STA 的所有调用都是连续的。即便如此,在 STA 进行单元间调用时允许重入调用,因此这并不是真正的类似锁的保证。

    调用序列化真的很粗糙,因为它是在单元级别,所以对同一个 STA 的所有调用,无论对象如何,都将一次执行一个(但可能以可重入的方式一个在另一个之上)。


    编辑:可以使用IMessageFilter 控制呼叫重新进入。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-22
      • 1970-01-01
      • 2011-04-13
      • 2014-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多