No se puede convertir el objeto COM de excepción de tipo

Tengo el siguiente código:

public void Test(IMyInterface iInterface) { iInterface.CallMethod ( ); } 

Que funciona bien. Sin embargo, si cambio el código a ser enhebrado:

 private IMyInterface myInterface; public void Test(IMyInterface iInterface) { myInterface = iInterface; new Thread ( new ThreadStart ( CallInterfaceMethod) ).Start ( ); } public void CallInterfaceMethod ( ) { myInterface.CallMethod ( ) } 

Cuando uso el hilo recibo la excepción:

No se puede convertir el objeto COM del tipo ‘System .__ ComObject’ al tipo de interfaz ‘IMyInterface’. Esta operación falló porque la llamada a QueryInterface en el componente COM para la interfaz con IID ‘{GUID}’ falló debido a un error de seguimiento: No se admite dicha interfaz

Pero la interfaz debe ser compatible muy bien? ¿Alguien tiene alguna idea sobre lo que está pasando aquí?

Esta desagradable, desagradable excepción surge debido a un concepto conocido como com marshalling. La esencia del problema radica en el hecho de que para consumir objetos COM de cualquier subproceso, el subproceso debe tener acceso a la información de tipo que describe el objeto COM.

En su escenario descrito, la razón por la que falla en el segundo subproceso es porque el segundo subproceso no tiene información de tipo para la interfaz.

Puedes intentar agregar lo siguiente a tu código:

 [ComImport] [Guid("23EB4AF8-BE9C-4b49-B3A4-24F4FF657B27")] public interface IMyInterface { void CallMethod(); } 

Básicamente, la statement anterior instruye al .NET framework COM cargado para cargar información de tipo usando técnicas tradicionales del registro y ubicar la biblioteca de tipos asociada y continuar desde allí.

También debe restringir la creación del objeto COM a un solo hilo (para evitar el ordenamiento de hilos) para ayudar a resolver este problema.

Para resumir, este error gira en torno a la información de tipo y el ordenamiento de hilos. Asegúrese de que cada subproceso que desea acceder al objeto COM tenga la información relevante para desmarcar el objeto del subproceso de origen.

PD: este problema se resuelve en .NET 4.0 usando una técnica llamada “Equivalencia de Tipo”

Recibí un consejo y me ayudó!

Busque en el hilo principal (Program.cs) la línea [STAThread] y cámbiela a [MTAThread].

He estado desarrollando una aplicación C # que utiliza 7-zip a través de interfaces COM. Me encontré con esta cosa divertida donde pude extraer archivos de un subproceso de trabajo en una instancia, pero no en otra, obteniendo esta misma excepción.

Descubrí que, mientras inicialice el objeto COM ofensivo en el subproceso donde se usa, no se lanzará ninguna excepción. Mi solución fue eliminar los objetos que utilizaban interfaces COM y reinicializarlos al pasarlos entre subprocesos.

Bueno, por un lado, está realizando una llamada de subproceso a un objeto sin bloquearlo, esto automáticamente causará algunos problemas. Su código debería verse más como:

 private IMyInterface myInterface; private static readonly object _myObjectLock = new object(); public void Test(IMyInterface iInterface) { myInterface = iInterface; new Thread ( new ThreadStart ( CallInterfaceMethod) ).Start ( ); } public void CallInterfaceMethod ( ) { lock(_myObjectLock) { myInterface.CallMethod ( ); } } 

Por lo que entiendo, el error que enumeró a veces puede ocurrir cuando no se puede acceder al recurso, lo que, con una operación de subprocesos como este, es muy probable que ocurra. Sin embargo, no me cites, no soy un experto en COM.

Sinceramente, no creo que me acerque a llamar a este método de esta manera, demasiados riesgos al hacerlo. ¿Ha considerado usar un ParameterizedThreadStart y pasar el objeto de esa manera? Aún necesitaría bloquear de forma segura sus objetos para las operaciones de subproceso, pero sería más seguro.

Además, verifique que su clase “myInterface” aún pueda llamar al método “CallMethod ()”. Las interfaces no tienen implementación, puede que tenga problemas al configurar “myInterface = iInterface”.