2012-08-31 213 views
6

私はデバイス照会にWMIを使用しています。新しいデバイスが挿入または削除されたときにUIを更新する必要があります(デバイスのリストを最新の状態に保つため)。アプリケーションは、別のスレッド用にマーシャリングされたインターフェイスを呼び出しました。

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

このコードは、私がLoadDevices方法の初めに

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

を入れ

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

次のテキストで例外をスローし、私はそれが常に同じと呼ばれていることを確認しますスレッド(1)。ここで何が起こっているのか、このエラーを取り除く方法を教えてください。

答えて

2

最後に新しいスレッドを使用して解決しました。 私はこのメソッドを分割したので、今はGetDiskDevices()LoadDevices(List<Device>)のメソッドがあり、私はInvokeLoadDevices()メソッドを持っています。

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

私は

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

おかげで呼び出すDBT_DEVICEARRIVALまたはDBT_DEVICEREMOVECOMPLETEメッセージのいずれかを取得します。あなたが使用することができW10のUWPについては

0

public async SomeMethod() 
{ 
    await CoreWindow.GetForCurrentThread().Dispatcher.RunAsync(CoreDispatcherPriority.High,() => 
     { 
      // Your code here... 
     }); 
} 
関連する問題