Frage

Ich schreibe eine App in C #, .NET 3.0 in VS2005 mit einer Funktion zur Überwachung Einführung / -ausgabe von verschiedenen Wechseldatenträgern (USB-Flash-Laufwerke, CD-ROMs etc.). Ich wollte nicht, WMI verwenden, da es manchmal mehrdeutig sein kann (zB es mehrere Einführungsveranstaltungen für ein einzelnes USB-Laufwerk erzeugen kann), so dass ich einfach die WndProc meiner Hauptform überschreibt die WM_DEVICECHANGE Nachricht zu fangen, wie vorgeschlagen hier . Gestern habe ich laufen in ein Problem, wenn es stellte sich heraus, dass ich WMI verwenden, muss auf jeden Fall ein paar obskure Platten Details wie eine Seriennummer abzurufen. Es stellt sich heraus, dass WMI ruft Routinen aus dem Inneren der WndProc die DisconnectedContext MDA wirft.

Nach einigem Graben ich, dass mit einer ungeschickten Abhilfe beendet. Der Code lautet wie folgt:

    // 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();

, die im Grunde bedeutet, das WMI-verwandte Verfahren auf einem separaten Thread ausgeführt wird - aber dann, warte auf sie vervollständigen zu.

Nun ist die Frage: Warum funktioniert es, und Warum muss es so sein? (Oder, nicht wahr?)

Das verstehe ich nicht die Tatsache der DisconnectedContext MDA oder RPC_E_WRONG_THREAD an erster Stelle zu bekommen. Wie funktioniert läuft GetDrives() Prozedur von einem Event-Handler unterscheidet Schaltfläche klicken sie von einem WndProc aus telefonieren? sie auf dem gleichen Hauptthread meiner App nicht passieren? BTW, ist meine app vollständig Single-Thread, also warum alle plötzlich einen Fehler zu einem gewissen ‚falschen Thread‘ bezieht? Impliziert die Verwendung von WMI-Multithreading und spezielle Behandlung von Funktionen aus System.Management?

In der Zwischenzeit fand ich eine andere Frage in Bezug auf die MDA, es ist hier . OK, ich kann es nehmen, dass WMI Mittel fordert einen separaten Thread für die zugrunde liegende COM-Komponente zu schaffen - aber es macht mir immer noch nicht auf, warum nicht-Magie ist erforderlich, wenn es ruft nach einer Taste gedrückt wird und Do-Magie benötigt wird, wenn Sie anrufen es aus dem WndProc.

Ich bin wirklich darüber verwirrt und würde eine Klarstellung in dieser Angelegenheit zu schätzen wissen. Es gibt nur wenige Dinge schlimmer als eine Lösung mit und ohne zu wissen, warum es funktioniert: /

Cheers, Aleksander

War es hilfreich?

Lösung

Es ist eine ziemlich lange Diskussion über COM Apartments und Nachrichtenpump MDA ausgelöst wird, aber die rekursive Aufrufe gegeben es sinnvoll der COM Kontext abgerissen werden kann, vorzeitig und / oder ein Objekt gesammelt zu übernehmen, bevor das zugrunde liegende COM-Objekt freigegeben werden kann.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top