C # InvalidOperationException AND, opération inter-thread

Dans mon formulaire Windows, j’ai une zone de texte et un bouton. La zone de texte “tb_LogBox” est une zone de texte multiligne. et l’exécuter, Visual Studio lève InvalidOperationException.

L’erreur réelle que j’obtiens L’opération inter-thread n’est pas valide: le contrôle ‘tb_LogBox’ accessible à partir d’un thread autre que le thread sur lequel il a été créé. L’exemple de code suivant illustre ce que j’essaie de faire.

private void button1_Click(object sender, EventArgs e) { try { var bw = new BackgroundWorker(); bw.DoWork += ExecuteOperations ; bw.RunWorkerAsync(); } catch (Exception ex) { tb_LogBox.AppendText(Environment.NewLine + " =@= " + ex.Message+" "+ex.Source); } } private void ExecuteOperations(object sender, DoWorkEventArgs e) { var FuncCall = new LogTimer(); tb_LogBox.AppendText(Environment.NewLine + FuncCall.DnT()); // the line i am getting the error. on } public class LogTimer { public ssortingng DnT() { const ssortingng datePat = @"d/MM/yyyy"; var dateTime = DateTime.Now(); return dateTime.ToSsortingng(datePat); } } 

Essayez d’utiliser la méthode begin invoke:

  BeginInvoke(new Action(() => { tb_LogBox.AppendText(Environment.NewLine + FuncCall.DnT()); })); 

Ce serait plus lisse que Invoke.

vous devez organiser le changement d’interface utilisateur sur le fil d’interface utilisateur. Cela peut être effectué en utilisant un appel invoke / begininvoke autour de votre tb_LogBox.AppendText

dans une application Winforms:

  this.BeginInvoke((MethodInvoker)delegate { tb_LogBox.AppendText(Environment.NewLine + FuncCall.DatenTime()); }); 

dans une application WPF:

  this.Dispatcher.BeginInvoke( (Action)delegate() { tb_LogBox.AppendText(Environment.NewLine + FuncCall.DatenTime()); }); 

J’espère que cela t’aides!

Faites ceci dans vos ExecuteOperations:

 tb_LogBox.Invoke((MethodInvoker)delegate() { tb_LogBox.AppendText(...) })); 

Vous ne pouvez pas utiliser d’autres threads (BackgroundWorker utilise un thread de threadpool .NET) pour apporter des modifications aux composants de l’interface utilisateur. C’est un obstacle majeur auquel vous devrez vous habituer dans la programmation WinForm.

Vous devez appeler la méthode du contrôle sur le thread d’interface utilisateur:

 private void ExecuteOperations(object sender, DoWorkEventArgs e) { var FuncCall = new LogTimer(); tb_LogBox.Invoke((MethodInvoker)delegate{ tb_LogBox.AppendText(Environment.NewLine + FuncCall.DatenTime()); }); } 

Je ne sais pas ce que fait LogTimer , mais il se peut très bien que vous deviez également créer cela à l’intérieur du délégué:

 private void ExecuteOperations(object sender, DoWorkEventArgs e) { tb_LogBox.Invoke((MethodInvoker)delegate{ var FuncCall = new LogTimer(); tb_LogBox.AppendText(Environment.NewLine + FuncCall.DatenTime()); }); } 

BackgroundWorker s’exécute sur son propre thread et toutes les opérations liées aux éléments d’interface graphique WinForms doivent s’exécuter sur le thread sur lequel elles ont été créées. La manière dont vous utilisez actuellement BackgroundWorker est identique à la mise en queue de l’opération à l’aide de ThreadPool.QueueUserWorkItem (). Pour renvoyer à l’interface graphique à l’aide de BackgroundWorker, utilisez ReportProgess ou définissez la propriété DoWorkEventArgs.Result dans la méthode de travail et réagissez aux événements correspondants sur le thread de l’interface graphique. Vous pouvez également utiliser Invoke / BeginInvoke sur un contrôle WinForms pour exécuter du code arbitraire directement sur le thread d’interface graphique. Dans votre cas, cela impliquerait de remplacer la ligne accédant à la tb_LogBox par:

 tb_LogBox.Invoke(new Action(() => tb_LogBox.AppendText(Environment.NewLine + FuncCall.DatenTime()); )); 

Vous ne pouvez pas accéder au thread hôte à partir du thread d’exécution du travailleur en arrière-plan. Vous pouvez utiliser la méthode ReportProgress de BackgroundWorker pour envoyer des informations au thread hôte.

 private void button1_Click(object sender, EventArgs e) { try { var bw = new BackgroundWorker(); bw.DoWork += ExecuteOperations; bw.ProgressChanged += bw_ProgressChanged; bw.RunWorkerAsync(); } catch (Exception ex) { tb_LogBox.AppendText(Environment.NewLine + " =@= " + ex.Message + " " + ex.Source); } } private static void ExecuteOperations(object sender, DoWorkEventArgs e) { var FuncCall = new LogTimer(); ssortingng text = Environment.NewLine + FuncCall.DnT(); (sender as BackgroundWorker).ReportProgress(0, text); } private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e) { tb_LogBox.AppendText(e.UserState as ssortingng); } public class LogTimer { public ssortingng DnT() { const ssortingng datePat = @"d/MM/yyyy"; var dateTime = DateTime.Now; return dateTime.ToSsortingng(datePat); } }