DisconnectedContext MDA при вызове функций WMI в однопоточном приложении

Я пишу приложение на C #, .NET 3.0 в VS2005 с функцией мониторинга вставки / извлечения различных съемных носителей (USB-флеш-накопители, CD-ROM) и т.д.). Я не хотел использовать WMI, поскольку иногда он может быть неоднозначным (например, он может порождать несколько событий вставки для одного USB-накопителя), поэтому я просто переопределяю WndProc моей основной формы, чтобы поймать сообщение WM_DEVICECHANGE, как предлагается здесь . Вчера я столкнулся с проблемой, когда выяснилось, что мне все равно придется использовать WMI для получения некоторых непонятных сведений о диске, таких как серийный номер. Оказывается, вызов подпрограмм WMI из WndProc вызывает MDA DisconnectedContext.

Покопавшись, я нашел неудобный обходной путь. Код выглядит следующим образом:

    // the function for calling WMI 
    private void GetDrives()
    {
        ManagementClass diskDriveClass = new ManagementClass("Win32_DiskDrive");
        // THIS is the line I get DisconnectedContext MDA on when it happens:
        ManagementObjectCollection diskDriveList = diskDriveClass.GetInstances();
        foreach (ManagementObject dsk in diskDriveList)
        {
            // ...
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        // here it works perfectly fine
        GetDrives();
    }


    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);

        if (m.Msg == WM_DEVICECHANGE)
        {
            // here it throws DisconnectedContext MDA 
            // (or RPC_E_WRONG_THREAD if MDA disabled)
            // GetDrives();
            // so the workaround:
            DelegateGetDrives gdi = new DelegateGetDrives(GetDrives);
            IAsyncResult result = gdi.BeginInvoke(null, "");
            gdi.EndInvoke(result);
        }
    }
    // for the workaround only
    public delegate void DelegateGetDrives();

, что в основном означает выполнение процедуры, связанной с WMI, в отдельном потоке, но затем ожидание ее завершения.

Теперь вопрос: почему это работает, и почему так должно быть? (или не так ли?)

Я не понимаю факта получения MDA DisconnectedContext или RPC_E_WRONG_THREAD в первую очередь. Чем отличается выполнение процедуры GetDrives () из обработчика события нажатия кнопки от ее вызова из WndProc? Разве они не происходят в одном и том же основном потоке моего приложения? Кстати, мое приложение полностью однопоточное, так почему же вдруг возникла ошибка, относящаяся к какой-то «неправильной нити»? Подразумевает ли использование WMI многопоточность и особую обработку функций из System.Management?

Тем временем я нашел еще один вопрос, связанный с этим MDA, это здесь . Хорошо, я могу понять, что вызов WMI означает создание отдельного потока для базового COM-компонента, но мне все еще не приходит в голову, почему не требуется никакого волшебства при его вызове после нажатия кнопки, а при вызове требуется магия это из WndProc.

Я действительно смущен этим и был бы признателен за некоторые разъяснения по этому поводу. Есть только несколько вещей хуже, чем иметь решение и не знать, почему оно работает: /

Ура, m действительно смущен этим и был бы признателен за некоторые разъяснения по этому поводу. Есть только несколько вещей хуже, чем иметь решение и не знать, почему оно работает: /

Ура, m действительно смущен этим и был бы признателен за некоторые разъяснения по этому поводу. Есть только несколько вещей хуже, чем иметь решение и не знать, почему оно работает: /

Ура, Александр

10
задан Community 23 May 2017 в 12:34
поделиться