2

J'ai toujours eu beaucoup de problèmes avec BackgroundWorkers en C# pour une raison quelconque; leur concept semble vraiment me bloquer, donc j'espère que c'est un problème assez basique et que quelque chose peut être corrigé assez facilement ...C# - BackgroundWorker Mise à jour constante du contrôle: Erreur!

J'ai deux formes qui utilisent .NET remoting pour communiquer d'avant en arrière. En ce moment, modifier un paramètre sur Form1 provoque quelque chose à changer sur Form2 et cela fonctionne très bien. Cependant, maintenant je dois faire fonctionner la même chose dans l'autre sens (changer quelque chose sur Form2 provoque la mise à jour de Form1) et je ne peux pas le faire de la même façon (je ne peux pas à Form1). En ce moment, j'essaie d'utiliser un BackgroundWorker sur Form1 pour appeler constamment une méthode 'Update()' sur chacun des sous-contrôles (qui sont placés sur Form1). Chacun de ces contrôles a le moyen de saisir l'état actuel de leurs paramètres équivalents à partir de Form2 et de se mettre à jour (cela fonctionne bien, la méthode 'Update()' est déjà considérée comme travaillant sur l'initialisation de Form1).

Voici où mon problème se pose. Je ne savais pas comment faire en sorte que BackgroundWorker appelle constamment 'Update()' sur chacun des formulaires, donc dans ma méthode 'DoWork()', j'ai une boucle "while (true)" et dans lequel BackgroundWorker appelle la 'Update() 'méthode de chaque sous-contrôle, puis dort pendant une très courte période, puis répète. En procédant de cette façon, j'obtiens une erreur "InvalidOperationException was non gérée par le code utilisateur" avec des détails indiquant que "l'opération cross-thread n'est pas valide: Control 'comboBox_BGColor' accédé à partir d'un thread autre que le thread sur lequel il a été créé. " Maintenant, je sais essentiellement ce que cela signifie et je comprends pourquoi c'est arrivé, cependant, je ne sais pas quoi faire différemment ou comment changer les choses pour le faire fonctionner comme vous le souhaitez. Quelqu'un at-il des conseils sur ceci ou la façon dont j'utilise BackgroundWorker? Merci beaucoup pour toute information et pour avoir pris le temps de lire ceci!

Répondre

3

Les contrôles UI ont une affinité de fil . Vous ne devriez pas toucher les commandes (pour lire ou écrire) à partir de n'importe quel fil, sauf le fil de l'interface utilisateur. Si le parle principalement à l'interface utilisateur, vous seriez probablement mieux avec un contrôle Timer, évitant le besoin d'appeler Invoke ou BeginInvoke beaucoup de fois.

Cependant, généralement Je préférerais une conception à base plus « observateur » ici, avec des événements de changement de notification (soit FooChanged ou INotifyPropertyChanged) et événements-gestionnaires qui font l'interface utilisateur pour refléter les changements.

1

vous avez besoin de contrôle de la minuterie au lieu de travailleur de fond

1

L'exception que vous recevez serait le résultat de l'appel Update() (qui modifie une ou plusieurs formes dans votre thread principal) directement à partir _DoWork au sein du fil de votre BackgroundWorker.

Si vous allez utiliser la méthode BackgroundWorker:

  • Définissez votre propriété travailleur .WorkerReportsProgress à true
  • Lorsque vous effectuez votre boucle, utilisez la méthode .ReportProgress() du travailleur pour déclencher l'événement _ProgressChanged du travailleur gestionnaire.
  • Le gestionnaire d'événements _ProgressChanged peut alors effectuer un appel à Update() de votre formulaire méthode en toute sécurité

Si vous vous éloignez d'utiliser le travailleur (surtout si votre travailleur de fond existe uniquement pour cette boucle), je Je vous suggère d'aller avec Marc's suggestion de gestionnaires d'événements standard. Cette route va générer moins de temps processeur (même si cela est minime pour le moment) que d'ajouter dans votre boucle externe ou un contrôle Timer.

L'une ou l'autre route doit adresser l'exception Cross-thread.

Questions connexes