Как использовать Marshal.ReleaseComObject с собственными функциями Win32 - PullRequest
7 голосов
/ 22 апреля 2009

Я играю с этими двумя собственными функциями 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 );

И мне трудно понять, нужно ли мне / нужно вызвать Marshal.ReleaseComObject для любого из возвращаемых объектов. Я был бы благодарен, если бы кто-то мог просветить меня на эту тему! Вот пример использования:

    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;
    }

1 Ответ

6 голосов
/ 22 апреля 2009

Marshal.ReleaseComObject - полезный обходной путь, если вам действительно нужно, чтобы GC немедленно применил релиз, вместо того, чтобы ждать запуска GC. Лучше не использовать его, если вам действительно не нужно, потому что он имеет тенденцию захватывать ваш код, и вы должны применять его везде, включая места, где вы создали неявные ссылки.

Я подозреваю, что лучший способ взаимодействия COM в .Net - это написание строго типизированных классов-оболочек для используемых вами методов. Таким образом, нет возможности вводить неявные ссылки, и это упростит код и обеспечит более легкий доступ к интерфейсам для GC. Некоторые из моих коров-орков сообщили об улучшении поведения памяти с помощью этих методов - объекты освобождаются своевременно, поскольку GC работает, не оставляя никаких загадочных ссылок.

Вообще говоря, все объекты COM, на которые есть ссылки в коде .Net, реализованы в форме объекта RCW, который содержит истинную ссылку COM - вызов ReleaseComObject заставляет RCW уменьшить ссылку на счетчик единиц. Таким образом, это похоже на простой вызов Release для действительного экземпляра IUnkown. Возможно, в приведенном выше примере нет необходимости совершать вызов.

...