Вопрос

Примечание:

  • С использованием сырой Win32 CreateTheard() API
  • Нет МФЦ
  • Интерфейс — это просто указатель на виртуальную таблицу.

Вопрос:

  • Как передать указатель интерфейса в поток?

Иллюстрация:

IS8Simulation *pis8 = NULL;

...

CoCreateInstance(
                 clsid,
                 NULL,
                 CLSCTX_LOCAL_SERVER,
                 __uuidof(IS8Simulation),
                 (void **) &pis8);



...

hThread = CreateThread(
                NULL,
                0,
                SecondaryThread,
                //interface pointer pis8
                0,
                &dwGenericThreadID);

...

DWORD WINAPI SecondaryThread(LPVOID iValue)
{
    //using iValue accordingly
    //E.g.: iValue->Open

С уважением

Это было полезно?

Решение

Как было указано ниже, прохождение COM Указатель интерфейса между потоками небезопасен.

Предполагая, что вы знаете, что делаете:

hThread = CreateThread(
                NULL,
                        0,
                        SecondaryThread,
                        (LPVOID) pis8
                        0,
                        &dwGenericThreadID);

DWORD WINAPI SecondaryThread(LPVOID iValue)
{
   ((IS8Simulation*) iValue)->Open();
}

Потокобезопасная версия:

void MainThread()
{
    IStream* psis8;
    HRESULT res = CoMarshalInterThreadInterfaceInStream (IID_IS8SIMULATION, pis8, &psis8);
    if (FAILED(res))
         return;
    hThread = CreateThread(
                NULL,
                0,
                SecondaryThread,
                (LPVOID) psis8
                0,
                &dwGenericThreadID
          );
}

DWORD WINAPI SecondaryThread(LPVOID iValue)
{
   IS8Simulation* pis8;
   HRESULT res = CoGetInterfaceAndReleaseStream((IStream*) iValue, IID_IS8SIMULATION, &pis8);
   if (FAILED(res))
      return (DWORD) res;
   pis8->Open();
}

Другие советы

Если интерфейс в вашем вопросе является COM-интерфейсом, подхода, предложенного Quassnoi, может быть недостаточно.Вы должны обратить внимание на потоковую модель используемого COM-объекта.Если вторичный поток присоединится к отдельной COM-квартире, отличной от той, в которой был создан ваш COM-объект, и если этот объект не гибкий в квартире, вам нужно будет маршалировать этот указатель интерфейса, чтобы вторичный поток получил прокси, а не прямой указатель на объект.

COM-объект обычно становится гибким с помощью специальной реализации IMarshal.Самый простой подход — агрегировать Free Threaded Marshaler.

Несколько полезных ссылок...

Обновлять:О свободном маршалере...

Из комментариев по этой теме становится ясно, что некоторые люди рекомендуют никогда не прикасаться к FTM.Хотя «Эффективный COM» — отличная книга, я думаю, что некоторые из ее рекомендаций открыты для интерпретации.В пункте 33 говорится: «Остерегайтесь FTM»;там не написано «Никогда не используйте FTM».Очень мудро рекомендуется соблюдать осторожность, особенно когда ваш гибкий к апартаментам объект содержит ссылки на другие объекты, потому что они могут не быть гибкими к апартаментам.Итак, на самом деле совет:При создании гибких объектов тщательно подумайте, используют ли они FTM для достижения своей гибкости.Если вы уверены, что можете построить гибкий объект, я не вижу причин, по которым вы бы не использовали FTM для достижения этой цели.

В основном вам нужно сделать следующее:

  • CoMashalInterThreadInterfaceInStream ==> вы получаете интерфейс IStream.
  • передать этот IStream в поток, например.как сказал Куасной.
  • в SecondaryThread вызовите CoGetInterfaceAndReleaseStream получить интерфейс (или прокси к нему, если необходимо).

Не освобождайте интерфейс IStream, если создание потока не завершится неудачно, и не выходите из потока, пока вы не позвоните. CoGetInterfaceAndReleaseStream.

Среда выполнения COM автоматически создаст для вас прокси.Прокси гарантирует, что, например.COM-компонент с квартирным потоком вызывается в потоке, который его создал.Однако для этого также необходимо, чтобы:

  • Интерфейс — IDispatch, или для интерфейса зарегистрированы компоненты прокси/заглушки.
  • поток, создавший компонент, имеет цикл обработки сообщений и обрабатывает сообщения
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top