2010-02-01 18 views
7

Soy nuevo en COM y trato de entender la diferencia entre STA y MTA. Traté de crear un ejemplo que muestre que COM puede administrar llamadas al objeto creado en STA que no es seguro para subprocesos.No se puede llamar al objeto COM creado a partir de STAThread desde sus hilos STA

MyCalcServer clase aquí se crea utilizando ATL Simple Object. Los ajustes utilizados son los mismos que en this article:

  • modelo de subprocesos: Apartamento
  • Agregación: Sin
  • Interfaz: personalizada

MyCalcServer objeto COM se utiliza en otro proyecto de C# que es:

class Program 
{ 
    [STAThread] 
    static void Main(string[] args) 
    { 
     MyCOMLib.MyCalcServer instance = new MyCOMLib.MyCalcServer(); 
     string output1; 
     instance.ChangeValue("Gant", out output1); 
     Console.WriteLine(output1); 


     Thread t1 = new Thread(() => 
     { 
      while (true) 
      { 
       string output; 
       instance.ChangeValue("Gant", out output); 
       Console.WriteLine(output); 
      } 
     }); 
     t1.SetApartmentState(ApartmentState.STA); 
     t1.Start(); 

     // : 
     // also has t2 and t3 here with similar code 
     // : 

     t1.Join(); t2.Join(); t3.Join(); 

    } 
} 

Sin embargo, esto siempre da como resultado InvalidCastException (E_NOINTERFACE) levantado dentro del código de t1. También intenté cambiar ApartmentState por MTA sin éxito.

Unable to cast COM object of type 'MyCOMLib.MyCalcServerClass' to interface type 'MyCOMLib.IMyCalcServer'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{B005DB8C-7B21-4898-9DEC-CBEBE175BB21}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

¿Alguien podría explicar lo que estoy haciendo mal aquí?

+0

Tal vez el JIT cree que no está utilizando "instancia" y lo lanza temprano. intenta poner Marshal.ReleaseComObject (instancia) después de las uniones. – adrianm

+0

@adrianm Todavía no funciona pero gracias por esto – Gant

+0

Intente cambiar la primera línea a MyCOMLib.IMyCalcServer instancia = new MyCOMLib.MyCalcServer(); Creo que solo las interfaces (no las clases) se pueden ordenar entre subprocesos. – adrianm

Respuesta

3

Solicita explícitamente a COM que cree una instancia para el hilo principal, luego pasa esto a otro hilo. Por supuesto, en alguna circunstancia está permitido (por ejemplo, declarar MyCalcServer como multiproceso).

Pero en su caso parece que necesita crear proxy para otro hilo. En clientes COM regulares, lo hace CoMarshalInterThreadInterfaceInStream. Hay un artículo grande para aclararlo http://www.codeproject.com/KB/COM/cominterop.aspx

+2

El contenedor .Net realiza la clasificación entre hilos automáticamente (de lo contrario, el finalizador no funcionaría). Si el Mariscal automático no funcionó, el error sería E_WRONG_THREAD (8001010E) – adrianm

1

Logré obtener esta resolución.

Como soy nuevo en COM, no sé mucho sobre Proxy/Stub y que se necesitan para reunir productos entre STA y STA. Después de crear un nuevo proyecto ATL y asegurarme de que tenga "Merge Proxy/Stub" marcado. El problema desapareció

que encontrar la información de esta página útil: Why would I want to merge Proxy/Stub code with my DLL project.

Proxy/stubs providing standard marshaling for your component. In many cases a DLL-based component may not need proxy/stub because it is running in the same context of its client, and this option may seem useless at first. However, COM uses the marshaling process to synchronize access to a component in multi-threaded situations. So, a DLL-based component will need a proxy/stub DLL in at least two cases:

  • It's running a multi-threaded client and needs to pass interface pointer between apartments (STA to STA or MTA to STA).

  • DCOM can provide a surrogate process for a DLL-based component so that it can be accessed in a distributed environment. In this case a proxy/stub is needed to marshal between machines.

By merging the proxy/stub code with your implementation, you don't have to distribute two DLLs, just the one.

marcaré @ respuesta de Dewfy como aceptar como él ha arrojado algo de luz sobre el tema de proxy.

Cuestiones relacionadas