Pregunta ¿Por qué utilizar FinalReleaseComObject en lugar de ReleaseComObject?


Sé la diferencia básica como ReleaseComObject solo disminuye un contador por uno y FinalReleaseComObject lo disminuye a cero.

Entonces, lo que suelo escuchar es llamar FinalReleaseComObject porque entonces está seguro de que el objeto COM realmente se ha liberado.

Pero esto me hace preguntarme, hay un punto en este contador ¿no? ¿No estás rompiendo ese mecanismo si siempre llamas FinalReleaseComObject. Si ese contador no es uno antes de llamar ReleaseComObject, ¿no hay probablemente una razón para eso?

¿Qué podría causar que sea más alto que uno cuando no debería ser?

Gracias por adelantado.

PD: Mi experiencia COM solo consiste en usar Interoperabilidad de Excel. No estoy seguro de si esta pregunta es local para ese dominio (es decir, fuera de Office Interop, FinalReleaseComObject no se usa a menudo).

Actualización 1

los artículo Dan mencionó conversaciones sobre el uso ReleaseComObject cuando termines. Como entiendo de la artículo, esta es la forma normal. Creo que si haces esto constantemente, debería funcionar bien. En un comentario a la artículo el autor sugiere que alguien llame ReleaseComObject en un bucle hasta que realmente se libere (el artículo es de 2006, por lo que esto es análogo a llamar FinalReleaseComObject) Pero también afirma que esto podría ser peligroso.

Si realmente desea que el RCW llame a Release () en un punto particular del código, puede llamar a ReleaseComObject () en un bucle hasta que el valor de retorno llegue a cero. Esto debería garantizar que el RCW llamará a Release (). Sin embargo, si lo hace, tenga cuidado, cuando las otras referencias administradas intenten usar ese RCW, causará una excepción ".

Esto me lleva a creer que de hecho no una buena idea para llamar siempre FinalReleaseComObject, ya que puedes causar excepciones en otros lugares. Tal como lo veo ahora, solo debes llamar a esto si estás absolutamente seguro de que puedes hacerlo.

Aún así, tengo poca experiencia en este asunto. No sé cómo puedo estar seguro. Si el contador aumenta cuando no debería, ¿no es mejor solucionar ese problema? Si es así, entonces yo diría FinalReleaseComObject es más un truco que una mejor práctica.


32
2017-12-01 15:50


origen


Respuestas:


Algunos preámbulos ...

Un Contenedor invocable en tiempo de ejecución (RCW) solo llama a IUnknown.AddRef una vez en la interfaz COM no administrada que se ajusta. Sin embargo, un RCW también mantiene un recuento separado del número de referencias administradas que hay para el RCW. Es este conteo separado de referencias administradas el que se reduce mediante una llamada a Marshal.ReleaseComObject. Cuando el recuento de referencias administradas llega a cero, el RCW llama a IUnknown. Libere una vez en la interfaz COM no administrada.

Marshal.FinalReleaseComObject lleva el recuento de referencia administrado a cero con una sola llamada y, por lo tanto, invoca el método IUnknown.Release no administrado y envuelto inmediatamente (suponiendo que el recuento de referencias administradas no fuera cero).

Entonces, ¿por qué tienen Marshal.ReleaseComObject y Marshal.FinalReleaseComObject? Llamar a Marshal.FinalReleaseComObject simplemente evita tener que escribir un bucle que llama a Marshal.ReleaseComObject repetidamente hasta que devuelve 0 cuando desea indicar que ha De Verdad terminado de usar un objeto COM ahora.

¿Por qué usar Marshal.ReleaseComObject o Marshal.FinalReleaseComObject? Hay dos razones por las que soy consciente:

El primero es garantizar que los recursos no administrados (como los identificadores de archivos, memoria, etc.) utilizados por el objeto COM envuelto se liberen lo antes posible como resultado de la llamada resultante al método no administrado IUnknown.Release ().

El segundo es garantizar que el hilo que llama al método no administrado IUnknown.Release () está bajo su control, y no el hilo del finalizador.

Sin llamadas a ninguno de estos métodos de Marshal, el finalizador de RCW finalmente llame al método no administrado IUnknown.Release () algún tiempo después de que se haya recogido el archivo RCW.

Para detalles corroborativos, vea la entrada del blog del Equipo de Visual C ++ Mezcla de limpieza determinista y no determinista 


35
2017-12-01 18:00