interop - office - El objeto COM que se ha separado de su RCW subyacente no se puede utilizar
interop office (2)
Estoy tratando de usar el OpcRcw.da.dll. Si interoplo esta dll dentro de un proyecto de consola de prueba, todo funciona, pero si compilo el proyecto dll para hacer mi interoperación gimnástica y colocar mi biblioteca en mi proyecto de consola, aparece este error:
No se puede utilizar el objeto COM que se ha separado de su RCW subyacente.
¿Qué se debe hacer con un proyecto de clase lib para no matar a la referencia RCW?
Es un poco difícil saber qué está haciendo tu aplicación real, pero parece que puedes estar creando una instancia del objeto COM y luego intentar acceder a él desde otro hilo, tal vez en un evento Timer.Elapsed. Si su aplicación es multihilo, necesita crear una instancia del objeto COM dentro de cada hilo en el que lo usará.
Esto puede suceder por varias razones, las más importantes que conozco están a continuación.
Manejadores de eventos sin fuertes referencias al delegado
Una persona que llama se suscribe a un evento en el objeto com sin mantener una referencia segura al delegado de devolución de llamada. Aquí hay un ejemplo de cómo hacer esto correctamente y cómo no hacerlo: la razón de esto es una fuerte referencia que debe mantenerse en el delegado, si se sale del alcance, el contenedor liberará el recuento de referencias para la interfaz Y las cosas malas pasarán.
public class SomeClass
{
private Interop.ComObjectWrapper comObject;
private event ComEventHandler comEventHandler;
public SomeClass()
{
comObject = new Interop.ComObjectWrapper();
// NO - BAD!
comObject.SomeEvent += new ComEventHandler(EventCallback);
// YES - GOOD!
comEventHandler = new ComEventHandler(EventCallback);
comObject.SomeEvent += comEventHandler
}
public void EventCallback()
{
// DO WORK
}
}
Llamadas a un contenedor de tiempo de ejecución desechable
La envoltura ha sido eliminada y las llamadas se están realizando después de haber sido eliminada. Una forma común de que esto ocurra es si un control está utilizando un control activex o un objeto COM y los controles Dispose () se consideran fuera de orden.
- Se llama a un formulario Close () llamado.
- System.Windows.Forms.Close () llamará a Dispose ()
- Se llamará a sus formularios virtuales Dispose (), lo que se espera que llame a base.Dispose () en algún lugar. Systems.Windows.Forms.Dispose () liberará todos los objetos COM y las sincronizaciones de eventos en el formulario, incluso desde controles secundarios.
- Si el control que posee un objeto com está dispuesto explícitamente después de base.Dispose () y si llama a algún método en su objeto COM, ahora fallarán y obtendrá el error "El objeto COM que se ha separado de su RCW subyacente no puede ser usado".
Pasos de depuración
Una buena manera de depurar este problema es hacer lo siguiente:
- Escriba una clase que herede de la clase Interop (también conocida como el envoltorio ejecutable o RCW).
- Sobrescribir DetachEventSink
- Anular Eliminar
- Llame a su nueva clase en lugar de llamar directamente a la clase de interoperabilidad
- Agregar punto de interrupción a DetachEventSink y disponer
- Ver quién está llamando a estos métodos fuera de orden
Otra cosa
Esto no está relacionado con este problema, pero mientras estamos en el tema, a menos que sepa lo contrario, recuerde siempre verificar que el subproceso desde el que se usan sus objetos COM esté marcado como STA. Puede hacer esto introduciendo el depurador y verificando el valor devuelto desde:
Thread.CurrentThread.GetApartmentState();