2012-08-31 13 views
6

Tôi đang sử dụng WMI để truy vấn thiết bị. Tôi cần cập nhật giao diện người dùng khi thiết bị mới được lắp hoặc tháo (để cập nhật danh sách thiết bị).Ứng dụng được gọi là giao diện đã được sắp xếp theo một chủ đề khác nhau

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

Mã này ném ngoại lệ với các văn bản sau đây

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

tôi đặt

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

vào đầu của phương pháp LoadDevices và tôi thấy rằng nó luôn luôn được gọi là so với cùng chủ đề (1). Bạn có thể vui lòng giải thích những gì đang xảy ra ở đây và làm thế nào để thoát khỏi lỗi này?

Trả lời

2

Cuối cùng tôi đã giải quyết nó bằng cách sử dụng chuỗi mới. Tôi chia phương pháp này, vì vậy bây giờ tôi có các phương thức GetDiskDevices()LoadDevices(List<Device>) và tôi có phương pháp 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); 
    } 
} 

Khi tôi nhận được một trong hai DBT_DEVICEARRIVAL hoặc DBT_DEVICEREMOVECOMPLETE thông điệp mà tôi gọi

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

Cảm ơn.

0

Đối với UWP trên w10, bạn có thể sử dụng:

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