2009-04-22 18 views
7

estoy jugando con estas dos funciones de Win32 nativas:Cómo utilizar Marshal.ReleaseComObject con funciones nativas Win32

[DllImport("oleacc.dll")] 
    public static extern int AccessibleObjectFromWindow(
      IntPtr hwnd, 
      int dwObjectID, 
      ref Guid refID, 
      ref Accessibility.IAccessible ppvObject); 
    [DllImport("oleacc.dll")] 
    public static extern uint AccessibleChildren(
     Accessibility.IAccessible paccContainer, 
     int iChildStart, 
     int cChildren, 
     [Out] object[] rgvarChildren, 
     out int pcObtained); 

y estoy teniendo un tiempo difícil averiguar si debería/necesidad de llamar Mariscal .ReleaseComObject en cualquiera de los objetos devueltos. ¡Estaría agradecido si alguien pudiera aclararme sobre este tema! He aquí una muestra de uso:

Accessibility.IAccessible test(
     int hWnd, 
     string accessName) 
    { 
     Guid guidCOM = new Guid(0x618736E0, 0x3C3D, 0x11CF, 0x81, 0xC, 0x0, 0xAA, 0x0, 0x38, 0x9B, 0x71); 
     Accessibility.IAccessible a = null; 

     AccessibleObjectFromWindow(
      new IntPtr(hWnd), 
      -4, 
      ref guidCOM, 
      ref a); 
     object[] children = new object[a.accChildCount]; 
     int z; 
     AccessibleChildren(a, 0, children.Length, children, out z); 
     foreach (Accessibility.IAccessible a2 in children) 
      try 
      { 
       if (a2.get_accName(0) == accessName) 
        return a2; 
      } 
      catch 
      { 
      } 
     return null; 
    } 

Respuesta

6

Marshal.ReleaseComObject es una útil solución alternativa si realmente necesita para obtener el GC para solicitar la liberación de inmediato, en lugar de esperar a que el GC para funcionar. Lo mejor es no usarlo a menos que realmente lo necesite, ya que tiene una tendencia a hacerse cargo de su código y debe aplicarlo en todas partes, incluidos los lugares donde ha creado referencias implícitas.

Sospecho que el mejor método para la interoperabilidad COM en .Net es escribir clases de envoltura fuertemente tipadas alrededor de los métodos que está utilizando. De esta forma no hay posibilidad de introducir referencias implícitas, y simplificará el código y asegurará que las interfaces sean más fácilmente accesibles para el GC. Algunos de mis cow-orkers han informado sobre un mejor comportamiento de la memoria al usar este método: los objetos se lanzan de manera oportuna mientras GC se ejecuta sin dejar ninguna referencia misteriosa por ahí.

En general, todos los objetos COM referenciados en el código .Net se implementan en forma de un objeto RCW que contiene la verdadera referencia COM - la llamada a ReleaseComObject obliga al RCW a disminuir la referencia por un conteo de uno. De esta forma, es similar a simplemente llamar al Release en la instancia real IUnkown. Probablemente en el ejemplo que tienes arriba, no es necesario hacer la llamada.

+0

El "mejor no usarlo" es * muy específico * al contexto. Cuando se trata de un complemento de Outlook, por ejemplo, * casi todo debe ser lanzado manualmente *. Si no lo hace, se producirán algunos errores realmente extraños ("over-releasing" hace lo mismo, por lo que la semántica de propiedad muy precisa debe resolverse en el código). Consulte [Cuándo liberar objetos COM en complementos de Office desarrollados en .NET] (http://www.add-in-express.com/creating-addins-blog/2008/10/30/releasing-office-objects- red/). –

+0

... por otro lado [Marshal.ReleaseComObject Considered Dangerous] (http://blogs.msdn.com/b/visualstudio/archive/2010/03/01/marshal-releasecomobject-considered-dangerous.aspx). Es simplemente malo. –

+0

En realidad, pst, esa historia larga del equipo VS me parece que es un caso especial. La historia más corta se captura aquí en esta publicación de blog anterior a la que hace referencia el que usted citó: http://blogs.msdn.com/b/cbrumme/archive/2003/04/16/51355.aspx. Presenta algunas reglas simples y fáciles de seguir para usar Marshal.ReleaseComObject. – Cheeso

Cuestiones relacionadas