【问题标题】:Expose a class as STA COM将类公开为 STA COM
【发布时间】:2010-07-19 15:28:25
【问题描述】:

我有一个小 c# 类,我需要将其公开为 COM。使用 COM 对象的工具需要我支持 STA。我的 COM 对象有什么特别需要做的吗?

(我知道 STAThread 属性,但是(除非我错了)它是为了表明 .net 中的执行线程要与 STA 兼容,而不是为了表明我的 COM 对象需要兼容) .

到目前为止,这是我的声明。有什么我需要补充的吗?

[ComVisible(true)] [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(ITestClass1))] [Guid("093A3701-2C53-4A31-97C5-0F3C205E5B4C")] public class Class1: ITestClass1 {..} [ComVisible(true)] [Guid("8D52F785-CDD8-4248-8AB7-97B8C19DE59B")] public interface ITestClass1 {..}

【问题讨论】:

    标签: c# .net com


    【解决方案1】:

    COM 服务器通过名为 ThreadingModel 的注册表项来通告它所需的线程模型。如果注册表项丢失或设置为“Apartment”,则默认为单线程。

    Regasm.exe 将此键设置为“Both”。这意味着您的服务器被声明为与 STA 线程和 MTA 线程兼容。在某种程度上与 .NET 代码保持一致,它支持线程,但要求您必须注意线程安全。改这个很麻烦,你得自己写注册程序,用[ComRegisterFunction]属性注解。

    简单的方法是将键设置为“Both”并在您的类构造函数中检查公寓状态。使用 Thread.GetCurrentThread().GetApartmentState()。如果您获得 MTA,则抛出异常以告诉客户端您不支持多线程。许多 .NET 类都这样做。

    【讨论】:

    • 轻微错误:STA 不是默认值,缺少ThreadingModel 注册表项不会将线程模型设置为Apartment,而是设置为更严格的Main Thread Apartment 模型。 “主线程”对象是一个 STA 对象,具有附加约束,即无论哪个线程创建该对象,它都将在进程的主线程中创建。 “主线程”应该是调用CoInitialize() 和朋友的过程中的“第一个线程”,但我不知道如果第一个 CoInitializeEx() 调用是针对 MTA 会发生什么。
    • 人们确实对 COM 对象需要什么和线程提供什么之间的区别感到困惑。这个问题只与对象有关。 STA 和 MTA 是仅适用于线程的术语。
    【解决方案2】:

    请参阅this answer 以获取执行必要注册表巫术的 ComRegisterFunction 示例。在某些情况下,您可能需要这个 - 例如当您想确保您的线程是 STA 时,您可以与仅需要 STA 线程使用的其他 COM 对象进行交互。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-16
      • 2011-01-31
      • 1970-01-01
      • 2012-07-19
      • 2010-09-20
      • 1970-01-01
      • 2010-12-31
      • 2015-06-29
      相关资源
      最近更新 更多