Управление моделью потоков COM-объектов, обслуживаемых серверами .NET вне процесса - PullRequest
2 голосов
/ 11 октября 2010

При создании COM-сервера вне процесса в C #, как описано в примере кода Microsoft All-In-One: CSExeCOMServer , кажется трудным управлять моделью потоков объектов, которые создаются в сервер (клиентом).

Создаемый объект должен находиться в STA, поскольку он использует объекты WPF, а его фабрика регистрируется, как показано в строке 95 ExeCOMServer.cs , и вставляется ниже ...

private void PreMessageLoop()
{
    //
    // Register the COM class factories.
    // 

    Guid clsidSimpleObj = new Guid(SimpleObject.ClassId);

    // Register the SimpleObject class object
    int hResult = COMNative.CoRegisterClassObject(
        ref clsidSimpleObj,                 // CLSID to be registered
        new SimpleObjectClassFactory(),     // Class factory
        CLSCTX.LOCAL_SERVER,                // Context to run
        REGCLS.MULTIPLEUSE | REGCLS.SUSPENDED,
        out _cookieSimpleObj);
    if (hResult != 0)
    {
        throw new ApplicationException(
        "CoRegisterClassObject failed w/err 0x" + hResult.ToString("X"));
    }

Однако функция CreateInstance всегда вызывается в новом потоке, который находится в MTA. Кажется, не имеет значения, что основной поток локального сервера помечен (и проверен) как поток STA.

Все найденные материалы свидетельствуют о том, что квартира созданных объектов должна соответствовать квартире нити, в которой была зарегистрирована фабрика. Фактически, это, кажется, имеет место при использовании COM-сервера ATL (смешанного с Managed C ++ для создания объектов), но этот метод, по-видимому, внедряет новый поток в рабочий поток, который инициализирует параметры, особенно модель потоков COM. , не представляется изменяемым.

Кто-нибудь решил эту проблему, не прибегая к COM-серверу, написанному в основном неуправляемым кодом.

1 Ответ

2 голосов
/ 18 января 2011

У нас очень похожая ситуация в последнее время при настройке приложения WinForm для размещения некоторых объектов для 64-битного взаимодействия.Поток пользовательского интерфейса входит в STA при запуске (с атрибутом STAThread).Вскоре мы обнаружили, что все конструкторы выполняются в потоке пользовательского интерфейса (STA), но все остальные методы запускаются в рабочем потоке (MTA), который создает .Net.

Это не былоMTA - это проблема, но у нас есть методы, которые обращаются к пользовательскому интерфейсу, и тот факт, что они всегда запускаются в рабочем потоке, который нас беспокоит.Хотя мы не могли понять, как заставить .Net перенаправлять вызовы в поток пользовательского интерфейса (STA), мы придумали несколько очень грязных трюков, связанных с ContextBoundObject и перехватом методов.Я не буду вдаваться в подробности, но вы можете взглянуть на пространства имен System.Runtime.Remoting.Messaging и System.Runtime.Remoting.Contexts.Идея состоит в том, чтобы обманным путем заставить CCW рассматривать прозрачный прокси как объект взаимодействия, и мы перехватываем каждый вызов прокси, передаем сообщение в поток пользовательского интерфейса и затем переводим сообщение обратно в вызов метода.Грязные?Да.Спектакль?Очень плохой.Но это работает.

Если вы хотите увидеть код перехвата метода, вы можете отправить мне электронное письмо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...