Pergunta

Eu criei um objeto COM em processo (DLL) usando ATL. Note que este é um objeto e não um controle (por isso não tem nenhuma janela ou de interface do usuário.) O meu problema é que eu estou tentando disparar um evento de um segundo thread e eu estou recebendo uma 'falha catastrófica' (0x8000FFFF). Se eu disparar o evento do meu thread principal, então eu não obter o erro. O segundo segmento é chamar CoInitializeEx mas isso não faz diferença. Eu estou usando o modelo Apartamento rosqueamento, mas a mudança para livre de Listagem não ajuda.

O fato de que eu estou tentando fazer isso a partir de um segundo fio é, obviamente, crucial. Existe uma maneira fácil de fazer isso ou eu vou ter que implementar alguma forma janela escondida de mensagens?

Por exemplo, no meu arquivo de origem do objeto principal:

STDMETHODIMP MyObject::SomeMethod(...)
{
  CreateThread(NULL, 0, ThreadProc, this, 0, NULL);
  // Succeeds with S_OK
  FireEvent(L"Hello, world!");
  return S_OK;
}

DWORD WINAPI ThreadProc(LPVOID param)
{
  CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  MyObject* comObject = reinterpret_cast<MyObject*>(param);
  // Fails with 0x8000FFFF
  comObject->FireEvent(L"Hello, world!");
}

void MyObject::FireEvent(BSTR str)
{
  ...
  // Returns 0x8000FFFF if called from ThreadProc
  // Returns S_OK if called from SomeMethod
  pConnection->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);
}
Foi útil?

Solução

básico COM

Em STA suas vidas objeto em um único segmento (A Thread). Esta discussão é aquele que é criado em diante, seus métodos são executados no e é eventos são fogo diante. O STA torna-se de que não há dois métodos de seu objeto são executadas simultaneamente (porque eles têm que ser executado no thread por isso esta é uma boa conseqüência).

Isto não significa que o objeto não pode ser acessado de outros tópicos. Isto é feito através da criação de proxies do seu objeto para cada segmento que não seja o segmento. No segmento de embalar um IUnknown com CoMarshalInterThreadInterfaceInStream e, por outro fio de desembalar com CoGetInterfaceAndReleaseStream que realmente cria o proxy no outro segmento. Este proxy usa a bomba mensagem para chamadas de sincronização para você se oponha, chamadas que ainda são executados no segmento, de modo que o segmento tem de ser livre (não ocupado) para executar uma chamada de outro segmento.

No seu caso, você quer que seu objeto para ser capaz de executar métodos em um segmento e subir eventos em outro segmento. Portanto, este tem para acontecer no MTA, para que o seu objeto tem de viver em MTA, assim que sua classe tem de ser livre-threaded. Threads pertencer a exatamente um apartamento, portanto, um segmento não pode estar em MTA e STA simultaneamente. Se suas vidas objeto no MTA sempre que um objeto STA tenta usá-lo, terá de criar um proxy. Então você começa uma ligeira sobrecarga.

O que eu acho é que você está pensando em algum "técnica" muito inteligente para descarregar a sua thread principal, e fazer alguns eventos "assíncronos", que não vai voar no final :-)) Se você pensar sobre isso, tem a um ouvinte neste segundo [trabalhador] fio ...

Aliás, esta linha

MyObject* comObject = reinterpret_cast<MyObject*>(param);

pode ser feito em MTA somente.

Outras dicas

Eu acho que o verdadeiro problema não é o que o componente é configurado com, mas o processo host. Muitos anfitriões, como os negócio objeto queridos modelo, ao vivo em um único apartamento rosca caso em que não é permitido chamá-los de qualquer coisa, mas o segmento principal.
Se for esse o caso, você pode deixar COM fazer o trabalho usando o modelo único apartamento de rosca e mover a chamada real para uma função em uma CoClass e invocar essa função de seu segmento.
Isso só passa mensagens de janela nos bastidores também, mas poupa de implementar isso sozinho.

threading em COM (wikipedia): < br> O modelo Single-Threaded Apartment (STA) é um modelo muito utilizado. Aqui, um objeto COM está em uma posição semelhante à interface de usuário de um aplicativo de desktop. Em um modelo de STA, um único fio é dedicado a conduzir métodos de um objecto, isto é, um único fio é sempre utilizados para executar os métodos do objecto. Em tal arranjo, chamadas de método de tópicos fora do apartamento são empacotadas e automaticamente na fila pelo sistema (via uma fila de mensagens padrão do Windows). Assim, não há nenhuma preocupação sobre as condições de corrida ou a falta de sincronicidade, pois cada chamada de método de um objeto é sempre executado até o fim antes de outro é invocado.

Veja também mensagem de bombeamento no mesmo artigo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top