2010-07-23 2 views
2

J'ai une fonction qui ajoute un contrôle à un contrôle parent qui est appelé à partir de threads différents du thread sur lequel les contrôles ont été créés. Voici comment ça se passe:opération cross-thread même lors de l'exécution sur le thread UI

1  delegate void AddControlToParentDelegate(Control child, Control parent); 
2  private void addControlToParent(Control child, Control parent) { 
3  if (parent.InvokeRequired) { 
4   AddControlToParentDelegate d = new AddControlToParentDelegate(addControlToParent); 
5   this.Invoke(d, new object[] { child, parent }); 
6   } else { 
7    parent.Controls.Add(child); 
8   } 
9  } 
10 } 

Cela fonctionne bien jusqu'à deux parent.InvokeRequired ainsi que child.InvokeRequired sont vraies. Ensuite, une fois la ligne 5 exécutée (le délégué d est appelé et la fonction est supposée s'exécuter sur le thread de l'interface utilisateur.) (Right?)) child à la ligne 7 renvoie une exception invalide d'opération de threads croisés. Pourquoi est-ce? N'est-il pas déjà en cours d'exécution sur le thread il a été créé?

j'ai réussi à résoudre ce problème en ajoutant un chèque (child.InvokeRequired) supplémentaire:

delegate void AddControlToParentDelegate(Control child, Control parent); 
private void addControlToParent(Control child, Control parent) { 
    if (parent.InvokeRequired) { 
     AddControlToParentDelegate d = new AddControlToParentDelegate(addControlToParent); 
     this.Invoke(d, new object[] { child, parent }); 
    } else { 
     if (child.InvokeRequired) { 
      this.Invoke(new MethodInvoker(delegate() { 
      parent.Controls.Add(child); 
      })); 
     } else { 
      parent.Controls.Add(child); 
     } 
    } 
} 

mais cela semble terriblement juste bidouille-y et inutile. Est-ce la façon de le faire? Ou ai-je totalement raté le bus?

Répondre

6

Notez que InvokeRequired n'est pas fiable lorsque le contrôle n'a aucun handle de fenêtre. Ce sera presque certainement le cas pour un contrôle enfant nouvellement créé qui n'a pas encore de parent, ce qui semble être le cas dans votre code "fixe".

analyse détaillée Voir Ivan Krivyakov: http://www.ikriv.com/en/prog/info/dotnet/MysteriousHang.html

+3

En outre, des dessins qui ne * pas * utiliser 'InvokeRequired' sont plus maintenable. Je recommande de programmer une tâche sur le thread ui ou d'utiliser BackgroundWorker.ReportProgress, les deux étant des solutions indépendantes de la plate-forme (c'est-à-dire non liées à Windows Forms). –

Questions connexes