2012-08-31 1 views
6

Ich verwende WMI zum Abfragen von Geräten. Ich muss die Benutzeroberfläche aktualisieren, wenn ein neues Gerät eingefügt oder entfernt wird (um die Liste der Geräte auf dem neuesten Stand zu halten).Die Anwendung hat eine Schnittstelle aufgerufen, die für einen anderen Thread marshallt wurde.

private void LoadDevices() 
{ 
    using (ManagementClass devices = new ManagementClass("Win32_Diskdrive")) 
    { 
     foreach (ManagementObject mgmtObject in devices.GetInstances()) 
     { 
      foreach (ManagementObject partitionObject in mgmtObject.GetRelated("Win32_DiskPartition")) 
      { 
       foreach (ManagementBaseObject diskObject in partitionObject.GetRelated("Win32_LogicalDisk")) 
       { 
        trvDevices.Nodes.Add(...); 
       } 
      } 
     } 
    } 
} 

protected override void WndProc(ref Message m) 
{ 
    const int WM_DEVICECHANGE = 0x0219; 
    const int DBT_DEVICEARRIVAL = 0x8000; 
    const int DBT_DEVICEREMOVECOMPLETE = 0x8004; 
    switch (m.Msg) 
    { 
     // Handle device change events sent to the window 
     case WM_DEVICECHANGE: 
      // Check whether this is device insertion or removal event 
      if (
       (int)m.WParam == DBT_DEVICEARRIVAL || 
       (int)m.WParam == DBT_DEVICEREMOVECOMPLETE) 
     { 
      LoadDevices(); 
     } 

     break; 
    } 

    // Call base window message handler 
    base.WndProc(ref m); 
} 

Dieser Code löst eine Ausnahme mit dem folgenden Text

The application called an interface that was marshalled for a different thread.

Ich habe

MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString()); 

am Anfang LoadDevices Methode und ich sehe, dass es immer von derselben genannt wird Faden (1). Können Sie mir bitte erklären, was hier vor sich geht und wie Sie diesen Fehler beheben können?

Antwort

2

Schließlich habe ich es mit neuen Thread gelöst. Ich spalte diese Methode, so jetzt habe ich GetDiskDevices() und LoadDevices(List<Device>) Methoden und ich habe InvokeLoadDevices() Methode.

private void InvokeLoadDevices() 
{ 
    // Get list of physical and logical devices 
    List<PhysicalDevice> devices = GetDiskDevices(); 

    // Check if calling this method is not thread safe and calling Invoke is required 
    if (trvDevices.InvokeRequired) 
    { 
     trvDevices.Invoke((MethodInvoker)(() => LoadDevices(devices))); 
    } 
    else 
    { 
     LoadDevices(devices); 
    } 
} 

Wenn ich entweder von DBT_DEVICEARRIVAL oder DBT_DEVICEREMOVECOMPLETE Meldungen nenne ich

ThreadPool.QueueUserWorkItem(s => InvokeLoadDevices()); 

Dank.

0

Für UWP auf w10 Sie nutzen könnten:

public async SomeMethod() 
{ 
    await CoreWindow.GetForCurrentThread().Dispatcher.RunAsync(CoreDispatcherPriority.High,() => 
     { 
      // Your code here... 
     }); 
} 
Verwandte Themen