如何将暴露给COM-interop的.NET对象标记为单线程?

时间:2010-01-19 09:46:25

标签: c# .net com multithreading com-interop

在C ++中定义COM可见类时,我可以在头文件(threading(single)行)中定义支持的线程模型:

[
    coclass,
    default(IComInterface),
    threading(single),
    vi_progid("Example.ComClass"),
    progid("Example.ComClass.1"),
    version(1.0),
    uuid("72861DF5-4C77-43ec-A4DC-ED04396F0CCD")
]

是否有类似的方法在.NET中设置线程模型(例如属性)?我目前正在定义我的COM类:

[Guid("67155A91-2948-43f5-B07F-5C55CDD240E5")]
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IComInterface
{
    ...
}


[Guid("DC5E6955-BB29-44c8-9FC0-6AADEEB2AFFB")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("Example.ComClass")]
public class ComClass : IComInterface
{
    ...
}

- 编辑:

对标记答案的评论非常重要。似乎告诉RegAsm设置不同的ThreadingModel的唯一方法是编写一个标有[ComRegisterFunction]属性的自定义注册方法。

1 个答案:

答案 0 :(得分:6)

这真的很模糊,我从未见过MIDL中的“threading”属性。也没有MSDN Library authors

COM coclass使用HKCR\CLSID\{guid}\InProcServer32密钥在注册表中发布其线程要求。 ThreadingModel值声明它需要的公寓。如果它丢失或设置为“Apartment”,则宣布不是线程安全的并且需要来自STA线程的帮助。 CoCreateInstance()在创建对象时使用此值。如果当前线程不是STA,它将启动一个STA线程并创建一个代理,确保它始终以线程安全的方式使用。

[ComVisible] .NET类将注册为“Both”,表示可以在MTA中的线程上使用。非常乐观,但遵循.NET哲学,即一切都是线程不安全的,但可以通过将lock关键字放在正确的位置来保证安全。承诺通常不会被测试,风险很大。覆盖ThreadingModel值(或省略它)需要编写代码来自己注册coclass,用[ComRegisterFunction]属性修饰。 RegistrationServices.RegisterTypeForComClients()可用于将基本密钥放置到位。