Как пометить объекты .NET, подверженные COM-взаимодействию, как однопоточные? - PullRequest
7 голосов
/ 19 января 2010

При определении видимого COM-класса в C ++ я могу определить поддерживаемую модель потоков в файле заголовка (строка 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
{
    ...
}

- edit:

Комментарии к отмеченному ответу - действительно важная вещь.Кажется, что единственный способ сообщить RegAsm, что нужно установить другую ThreadingModel, - это написать собственный метод регистрации, помеченный атрибутом [ComRegisterFunction].

1 Ответ

6 голосов
/ 19 января 2010

Это действительно неясно, я никогда не видел атрибут "threading" в MIDL.Кроме того, авторы библиотеки MSDN .

COM-класс COM публикует свои требования к многопоточности в реестре, используя ключ HKCR\CLSID\{guid}\InProcServer32.Значение ThreadingModel объявляет квартиру, в которой она нуждается.Если он отсутствует или имеет значение «Квартира», он объявляет, что он не является поточно-ориентированным и требует помощи от потока STA.CoCreateInstance () использует это значение при создании объекта.При необходимости он запустит поток STA и создаст прокси, если текущий поток не является STA, гарантируя, что он всегда используется потокобезопасным способом.

A [ComVisible] .NET класс будет зарегистрирован как«Оба», указывая на то, что его можно использовать в потоке в MTA.Довольно оптимистично, но следует философии .NET, что все поточно-небезопасно, но можно сделать это безопасно, поместив ключевое слово lock в нужных местах.Обещание, которое не часто проверяется, кстати, рискованно.Переопределение значения ThreadingModel (или его пропуск) требует написания кода для самостоятельной регистрации кокласса, украшенного атрибутом [ComRegisterFunction].RegistrationServices.RegisterTypeForComClients () может быть полезен для установки основных ключей.

...