BackgroundWorker - cross thread operation not valid

I have a winform application (one form), there is a RichTextBox in this form. In the constructor of this form, I create an instance of the MyClass class. In "Form_Load", I call the Initialisation method from the MyClass instance.

In the form constructor

 myClass = new MyClass(RichTextBox richTextBox); 

In Form_Load

 myClass.Initialisation(); 

In the Initialisation method, in a loop, I read that some parmetologists do other things. In order not to freeze the application (because some operation may take some time, several seconds), I use BackgroundWorker . I use it like this (see code below).

When I execute, I get this error: the cross-stream operation is not valid: Control 'richTextBox access to them from the stream other than the stream on which it was created.

Could you tell me how to solve this? Work perfect when I don't get access to richTextBox

 public Class MyClass { static BackgroundWorker _bw; public MyClass() { _bw = new BackgroundWorker { WorkerReportsProgress = true, WorkerSupportsCancellation = true }; _bw.DoWork += bw_DoWork; _bw.ProgressChanged += bw_ProgressChanged; _bw.RunWorkerCompleted += bw_RunWorkerCompleted; } static void bw_DoWork(object sender, DoWorkEventArgs e) { foreach (....) { if (....) { richtextBox.Text.AppendText("MyText"); } } e.Result = true; } static void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){} static void bw_ProgressChanged(object sender, ProgressChangedEventArgs e){} } 
+9
c # winforms
Jan 05 '12 at 7:00
source share
7 answers

Using BackgroundWorker does not free you from the usual streaming rules - for example, only a user interface stream can access user interface components.

If you want to update the user interface from BackgroundWorker , in addition to using the progress / completion events (which occur in the user interface thread), you need to use Control.Invoke / Control.BeginInvoke in the same way as in other situations. For example:

 if (....) { Action action = () => richtextBox.Text.Add("MyText"); richtextBox.Invoke(action); // Or use BeginInvoke } 
+29
Jan 05 2018-12-12T00:
source share
— -

try this code

 BeginInvoke((MethodInvoker)delegate { richtextBox.Text.Add("MyText"); }); 
+11
Jan 05 2018-12-12T00:
source share

Using the BackgroundWorker component, the ProgressChanged and RunWorkerCompleted allow you to call methods / properties of user interface controls (which should always be executed in the user interface thread). As the user interface is DoWork in the DoWork event that runs on a thread other than the UI, you get this error, you may need to update the user interface controls using the Invoke or BeginInvoke methods in DoWork if you want.

+3
Jan 05 '12 at 7:19
source share

To make it cleaner and based on the assumption of John Skeet, I made an extension method that does the same, you can change this Label control to this TextBox control or just use this Control control (and basically allow each control will be easy to update):

 internal static class ExtensionMethods { /// <summary> /// Updates the label text while being used in a multithread app. /// </summary> /// <param name="control">The control.</param> /// <param name="text">The text.</param> internal static void UpdateThreadedText(this Label control, string text) { Action action = () => control.Text = text; control.Invoke(action); } /// <summary> /// Refreshes the threaded. /// </summary> /// <param name="control">The control.</param> internal static void RefreshThreaded(this Label control) { Action action = control.Refresh; control.Invoke(action); } } 

And then the use is pretty simple:

 this.yourLabelName.UpdateThreadedText("This is the text"); this.yourTextBoxName.UpdateThreadedText("This is the text"); this.yourControlName.UpdateThreadedText("This is the text"); 

or

 this.yourLabelName.RefreshThreaded(); 

Works well for me :)

+1
Oct 23 '13 at 11:29
source share

I think the error stops at this line:

 richtextBox.Text.Add("MyText"); 

Your question I look like this:

BackgroundWorker OnWorkCompleted throws a cross-thread exception

0
Jan 05 2018-12-12T00:
source share

Add

 e.Result = "MyText"; 

In bw_DoWork A:

 richTextBox1.AppendText((string)e.Result); 

In bw_RunWorkerCompleted

(change it to match your code)

EDIT:

If this has been done many times while BackgroundWorker running, you can add:

 _bw.ReportProgress(0, "MyText"); 

in bw_DoWork and:

 richTextBox1.AppendText((string)e.UserState); 

in bw_ProgressChanged .

0
Jan 05 2018-12-12T00:
source share

You can also try this.

 this.Invoke(new MethodInvoker(delegate() { richtextBox.Text.Add("MyText"); })); 
0
Aug 18 '16 at 3:41
source share



All Articles