2012-08-31 6 views
6

Sto utilizzando WMI per l'interrogazione dei dispositivi. Devo aggiornare l'interfaccia utente quando viene inserito o rimosso un nuovo dispositivo (per mantenere aggiornato l'elenco dei dispositivi).L'applicazione ha chiamato un'interfaccia che è stata sottoposta a marshalling per un thread diverso

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

Questo codice genera un'eccezione con il seguente testo

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

ho messo

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

all'inizio del metodo di LoadDevices e vedo che è sempre chiamato dallo stesso filo (1). Potresti spiegare cosa sta succedendo qui e come sbarazzarsi di questo errore?

risposta

2

Infine l'ho risolto utilizzando una nuova discussione. Ho diviso questo metodo, quindi ora ho i metodi GetDiskDevices() e LoadDevices(List<Device>) e ho il metodo 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); 
    } 
} 

Quando ottengo uno dei messaggi DBT_DEVICEARRIVAL o DBT_DEVICEREMOVECOMPLETE io chiamo

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

Grazie.

0

Per UWP su W10 è possibile utilizzare:

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