usa tipo sirve significado referencias referencia que programacion pero para nombres guia espacio como comando c# com ms-office office-pia rcw

tipo - RCW y recuento de referencias cuando se utiliza la interoperabilidad COM en C#



referencias de c# (5)

La solución aceptada es válida, pero aquí hay algunos antecedentes adicionales.

Un RCW contiene una o más referencias de interfaz de objeto COM nativas internamente para su objeto COM.

Cuando un RCW libera su objeto COM subyacente, ya sea debido a la recolección de basura o debido a que se Marshal.ReleaseComObject() a Marshal.ReleaseComObject() , libera todas sus interfaces de objetos COM mantenidas internamente.

En realidad, aquí hay muchos recuentos de referencias: uno determina cuándo RCW de .NET debería liberar sus interfaces de objetos COM subyacentes, y luego cada una de esas interfaces COM sin formato tiene su propio recuento de referencias como en COM normal.

Aquí está el código para obtener el recuento de referencia de la interfaz de COM IUnknown bruto:

int getIUnknownReferenceCount(object comobject) { var iUnknown = Marshal.GetIUnknownForObject(comObject); return Marshal.Release(iUnknown); }

Y puede obtener lo mismo para las otras interfaces COM del objeto utilizando Marshal.GetComInterfaceForObject() .

Además de las formas enumeradas en la solución aceptada , también podemos aumentar el recuento de referencias .NET RCW de forma artificial llamando a algo como Marshal.GetObjectForIUnknown() .

Este es un código de ejemplo que utiliza esa técnica para obtener el recuento de referencias RCW de un objeto COM dado:

int comObjectReferenceCount(object comObject) { var iUnknown = Marshal.GetIUnknownForObject(comObject); Marshal.GetObjectForIUnknown(iUnknown); Marshal.Release(iUnknown); return Marshal.ReleaseComObject(comObject); }

Tengo una aplicación que utiliza ensamblados de interoperabilidad de Office. Soy consciente de la "Runtime Callable Wrapper (RCW)" administrada por el tiempo de ejecución. Pero no estoy muy seguro de cómo se incrementa el recuento de referencias. MSDN dice:

RCW mantiene solo una referencia al objeto COM envuelto, independientemente de la cantidad de clientes administrados que lo llamen.

Si lo entiendo correctamente, en el siguiente ejemplo,

using Microsoft.Office.Interop.Word; static void Foo(Application wrd) { /* .... */ } static void Main(string[] args) { var wrd = new Application(); Foo(wrd); /* .... */ }

Estoy pasando la instancia wrd a otro método. Pero esto no incrementa el recuento de referencias internas. Así que me pregunto en qué escenarios se incrementa el recuento de referencia? ¿Alguien puede señalar un escenario en el que el recuento de referencia se incremente?

También leí un blog que dice evitar el uso de puntos dobles al programar con objetos COM. Algo así como, wrd.ActiveDocument.ActiveWindow . El autor afirma que el compilador crea variables separadas para mantener los valores que incrementarán el contador de referencia. En mi humilde opinión, esto es incorrecto y el primer ejemplo lo demuestra. ¿Es eso correcto?

Cualquier ayuda sería genial!


No deberías necesitar ningún tratamiento especial. El tiempo de ejecución solo mantiene una referencia al objeto COM. La razón de esto es que el GC rastrea todas las referencias administradas, por lo que cuando el RCW se sale del alcance y se recopila, se libera la referencia COM. Cuando pasa una referencia administrada, el GC lo está rastreando por usted: esta es una de las mayores ventajas de un tiempo de ejecución basado en GC sobre el antiguo esquema AddRef / Release.

No necesita llamar manualmente a Marshal.ReleaseComObject a menos que desee una versión más determinista.


No he visto el código para el RCW, ni siquiera estoy seguro de que sea parte del SSCLI, pero tuve que implementar un sistema similar para rastrear la vida útil de los objetos COM en SlimDX y tuve que hacer un poco de investigación en el RCW. Esto es lo que recuerdo, espero que sea razonablemente preciso pero tómalo con un toque de sal.

Cuando el sistema ve por primera vez un puntero de interfaz COM, simplemente va a un caché para ver si hay un RCW para ese puntero de interfaz. Presumiblemente, el caché estaría usando referencias débiles, para no evitar la finalización y la recopilación del RCW.

Si hay un envoltorio activo para ese puntero, el sistema devuelve el envoltorio; si la interfaz se obtuvo de una manera que incrementó el recuento de referencia de la interfaz, probablemente el sistema RCW llamaría Liberación () en este punto. Ha encontrado una envoltura en vivo, por lo que sabe que la envoltura es una sola referencia y quiere mantener exactamente una referencia. Si no hay un contenedor en vivo en el caché, crea uno nuevo y lo devuelve.

El contenedor llama Liberar en el (los) puntero (s) de la interfaz COM subyacente desde el finalizador.

La envoltura se encuentra entre usted y el objeto COM, y maneja todo el cálculo de parámetros. Esto también le permite tomar el resultado en bruto de cualquier método de interfaz que sea en sí mismo otro puntero de interfaz y ejecutar ese puntero a través del sistema de almacenamiento en caché RCW para ver si existe todavía antes de devolverle el puntero de interfaz ajustado.

Desafortunadamente, no entiendo bien cómo el sistema RCW maneja la generación de objetos proxy para enviar cosas a través de dominios de aplicaciones o subprocesos; No era un aspecto del sistema que necesitaba copiar para SlimDX.


También he estado investigando esta pregunta, trabajando en una aplicación centrada en interoperabilidad COM / .Net, combatiendo fugas, bloqueos y colisiones.

Respuesta corta: cada vez que el objeto COM se pasa del entorno COM a .NET.

Respuesta larga:

  1. Para cada objeto COM hay un objeto RCW [Prueba 1] [Ref 4]
  2. El recuento de referencias se incrementa cada vez que se solicita el objeto desde dentro del objeto COM (propiedad o método de llamada en el objeto COM que devuelve el objeto COM, el recuento de referencia del objeto COM devuelto se incrementará en uno) [Prueba 1]
  3. El recuento de referencias no se incrementa mediante la conversión a otras interfaces COM del objeto o moviendo la referencia RCW alrededor de [Prueba 2]
  4. El recuento de referencias se incrementa cada vez que se pasa un objeto como parámetro en el evento generado por COM [Ref 1]

En una nota al margen: SIEMPRE debe liberar objetos COM tan pronto como termine de usarlos. Dejar este trabajo al GC puede provocar fugas, comportamientos inesperados y puntos muertos en los eventos. Esto es diez veces más importante si accede al objeto que no está en el subproceso STA en el que se creó. [Ref 2] [Ref 3] [Experiencia personal dolorosa]

Espero haber cubierto todos los casos, pero COM es una cookie difícil. Aclamaciones.

Prueba 1 - recuento de referencias

private void Test1( _Application outlookApp ) { var explorer1 = outlookApp.ActiveExplorer(); var count1 = Marshal.ReleaseComObject(explorer1); MessageBox.Show("Count 1:" + count1); var explorer2 = outlookApp.ActiveExplorer(); var explorer3 = outlookApp.ActiveExplorer(); var explorer4 = outlookApp.ActiveExplorer(); var equals = explorer2 == explorer3 && ReferenceEquals(explorer2, explorer4); var count2 = Marshal.ReleaseComObject(explorer4); MessageBox.Show("Count 2:" + count2 + ", Equals: " + equals); } Output: Count 1: 4 Count 2: 6, Equals: True

Prueba 2 - conteo de referencias cont.

private static void Test2(_Application outlookApp) { var explorer1 = outlookApp.ActiveExplorer(); var count1 = Marshal.ReleaseComObject(explorer1); MessageBox.Show("Count 1:" + count1); var explorer2 = outlookApp.ActiveExplorer(); var explorer3 = explorer2 as _Explorer; var explorer4 = (ExplorerEvents_10_Event)explorer2; var explorerObject = (object)explorer2; var explorer5 = (Explorer)explorerObject; var equals = explorer2 == explorer3 && ReferenceEquals(explorer2, explorer5); var count2 = Marshal.ReleaseComObject(explorer4); MessageBox.Show("Count 2:" + count2 + ", Equals: " + equals); } Output: Count 1: 4 Count 2: 4, Equals: True

Fuentes que transmito además de mi experiencia y pruebas:

1. Johannes Passing''s - ¡Reglas de conteo de referencias RCW! = Reglas de conteo de referencias COM

2. Eran Sandler - Elementos internos envolventes que se pueden devolver en tiempo de ejecución y dificultades comunes

3. Eran Sandler - Marshal.ReleaseComObject y CPU Spinning

4. MSDN - Runtime Callable Wrapper


Marshal.ReleaseComObject llamar a Marshal.ReleaseComObject en su variable wrd para publicar su referencia a la aplicación word.

De esa manera, si Word no está visible y usted cierra su aplicación, el archivo ejecutable también se descargará a menos que usted lo haya hecho visible para el usuario.