J'ai un UserControl simple pour la pagination de base de données, qui utilise un contrôleur pour effectuer les appels DAL réels. J'utilise un BackgroundWorker
pour effectuer le levage lourd, et sur l'événement OnWorkCompleted
je réactiver certains boutons, modifiez une propriété TextBox.Text
et déclenchez un événement pour le formulaire parent.BackgroundWorker OnWorkCompleted lève l'exception de thread-thread
Le formulaire A contient mon UserControl. Quand je clique sur un bouton qui ouvre le formulaire B, même si je ne fais rien "là" et que je le ferme juste, et que j'essaie d'introduire la page suivante de ma base de données, le OnWorkCompleted
est appelé (et non mon fil principal), et jette une exception de thread-thread.
Au moment où j'ai ajouté une vérification pour InvokeRequired
au gestionnaire là, mais le point entier de OnWorkCompleted
ne doit-il pas être appelé sur le fil principal? Pourquoi cela ne fonctionnerait-il pas comme prévu?
EDIT:
J'ai réussi à limiter le problème à arcgis et BackgroundWorker
. J'ai la solution suivante qui ajoute une commande à arcmap, qui ouvre un simple Form1
avec deux boutons.
Le premier bouton exécute un BackgroundWorker
qui dort pendant 500ms et met à jour un compteur. Dans la méthode RunWorkerCompleted
, il vérifie InvokeRequired
et met à jour le titre pour montrer si la méthode était initialement utilisée dans le thread principal ou le thread de travail. Le deuxième bouton ouvre simplement Form2
, qui ne contient rien.
Au début, tous les appels à RunWorkerCompletedare
sont faites à l'intérieur du fil conducteur (Comme prévu - thats le point de whold de la méthode RunWorkerComplete, au moins par ce que je comprends de la MSDN sur BackgroundWorker
)
Après ouverture et En fermant Form2
, le RunWorkerCompleted
est toujours appelé sur le thread de travail. Je veux ajouter que je peux juste laisser cette solution au problème tel quel (vérifier InvokeRequired
dans la méthode RunWorkerCompleted
), mais je veux comprendre pourquoi cela se passe contre mes attentes. Dans mon "vrai" code je voudrais toujours savoir que la méthode RunWorkerCompleted
est appelée sur le thread principal.
j'ai réussi à détecter le problème à la commande form.Show();
dans mon BackgroundTesterBtn
- si j'utilise ShowDialog()
à la place, je reçois pas de problème (RunWorkerCompleted
fonctionne toujours sur le thread principal). J'ai besoin d'utiliser Show()
dans mon projet ArcMap, afin que l'utilisateur ne soit pas lié au formulaire. J'ai également essayé de reproduire le bug sur un projet WinForms normal. J'ai ajouté un projet simple qui ouvre juste le premier formulaire sans ArcMap, mais dans ce cas, je ne pouvais pas reproduire le bogue - le RunWorkerCompleted
a couru sur le fil principal, que j'aie utilisé Show()
ou ShowDialog()
, avant et après l'ouverture Form2
. J'ai essayé d'ajouter un troisième formulaire pour agir comme une forme principale avant mon Form1
, mais cela n'a pas changé le résultat.
Here est mon simple, sln (VS2005sp1) - il faut
ESRI.ArcGIS.ADF (9.2.4.1420)
ESRI.ArcGIS.ArcMapUI (9.2.3.1380)
ESRI.ArcGIS.SystemUI (9.2.3.1380)
Vérification msdn sur BackgroundWorker Je vois que je spécifiquement devrait utiliser l'événement RunWorkerCompleted pour gérer le formulaire. "Vous devez veiller à ne manipuler aucun objet de l'interface utilisateur dans votre gestionnaire d'événements DoWork, mais à communiquer à l'interface utilisateur via les événements ProgressChanged et RunWorkerCompleted." également - chaque fois que j'essaie un scénario plus simple, cela fonctionne bien et est appelé sur le fil principal. Comme dans l'exemple msdn là, ou la plupart du temps dans ma demande. C'est similaire à www.developmentnow.com/g/36_2008_3_0_0_1056508/Update-GUI-from-RunWorkerCompleted.htm –
C'est intéressant ... J'ai créé une application de test (application console) avec un simple travailleur de fond, et ça a déclenché chez le travailleur fil. Peut-être que le constructeur BackgroundWorker a de la magie qui le fait changer de comportement s'il est créé sur un thread d'interface utilisateur ou non? –