问题描述
在 C++ 中定义 COM 可见类时,我可以在头文件中定义支持的线程模型(threading(single)
行):
When defining a COM-visible class in C++ I can define the supported threading model in the header file (the threading(single)
line):
[
coclass,
default(IComInterface),
threading(single),
vi_progid("Example.ComClass"),
progid("Example.ComClass.1"),
version(1.0),
uuid("72861DF5-4C77-43ec-A4DC-ED04396F0CCD")
]
在 .NET 中设置线程模型是否有类似的方法(例如属性)?我目前这样定义我的 COM 类:
Is there a comparable way of setting the threading model in .NET (for example an attribute)? I currently define my COM-class as such:
[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]
属性的自定义注册方法.
The comments on the marked answer are the really important thing. It seems like the only way to tell RegAsm to set a different ThreadingModel is to write a custom registration method marked with the [ComRegisterFunction]
attribute.
推荐答案
这真的很晦涩,我从未见过 MIDL 中的threading"属性.MSDN Library 作者也没有.
That's really obscure, I've never seen the "threading" attribute in MIDL. Nor have the MSDN Library authors.
COM coclass 使用 HKCRCLSID{guid}InProcServer32
键在注册表中发布其线程要求.ThreadingModel 值声明了它需要的单元.如果它丢失或设置为Apartment",则宣布它不是线程安全的,需要 STA 线程的帮助.CoCreateInstance() 在创建对象时使用此值.如有必要,它会启动一个 STA 线程并在当前线程不是 STA 时创建一个代理,确保始终以线程安全的方式使用它.
A COM coclass publishes its threading requirements in the registry, using the HKCRCLSID{guid}InProcServer32
key. The ThreadingModel value declares the apartment it needs. If it is missing or is set to "Apartment" then is announces that is not thread-safe and requires help from an STA thread. CoCreateInstance() uses this value when it creates the object. If necessary it will start an STA thread and create a proxy if the current thread is not STA, ensuring it is always used in a thread-safe way.
[ComVisible] .NET 类将注册为Both",表示可以在 MTA 中的线程上使用.相当乐观,但遵循 .NET 哲学,即一切都是线程不安全的,但可以通过将 lock
关键字放在正确的位置来使其安全.顺便说一句,一个不经常测试的承诺是有风险的.覆盖 ThreadingModel 值(或省略它)需要编写代码来自己注册 coclass,并使用 [ComRegisterFunction] 属性进行修饰.RegistrationServices.RegisterTypeForComClients() 可用于获取基本密钥.
A [ComVisible] .NET class will be registered as "Both", indicating that it is okay to be used on a thread in the MTA. Pretty optimistic, but follows the .NET philosophy that everything is thread-unsafe but can be made safe by putting the lock
keyword in the right places. A promise that is not often tested btw, risky. Overriding the ThreadingModel value (or omitting it) requires writing code to register the coclass yourself, decorated with the [ComRegisterFunction] attribute. RegistrationServices.RegisterTypeForComClients() can be useful to get the basic keys into place.
这篇关于如何将暴露给 COM 互操作的 .NET 对象标记为单线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!