Click here to Skip to main content
15,881,757 members
Please Sign up or sign in to vote.
2.50/5 (2 votes)
See more:
So I am having a difficult problem:
Form1=> added a progress bar
Form2 => added a background worker
In the DoWork, I want to read a file into memory, than send that file to open in a richtextbox from Form2.

I am getting an error : "Cross-thread operation not valid: Richtextbox accessed from a thread other than the thread it was created on"

So, I searched google, and found put that I need to invoke the rochtextbox..

can you please help?
This is my code till now:

C#
void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {

            // Your background task goes here
            for (int i = 0; i <= 100; i++)
            {
                // Report progress to 'UI' thread
                backgroundWorker1.ReportProgress(i);

                string path = "articles\\" + name + ".dat";
                try
                {
                    using (FileStream fileStream = File.OpenRead(path))
                    {
                        MemoryStream memStream = new MemoryStream();
                        memStream.SetLength(fileStream.Length);
                        fileStream.Read(memStream.GetBuffer(), 0, (int)fileStream.Length);
                    }
                    richTextBox1.Invoke(new MethodInvoker(delegate { name1 = richTextBox1.Text; }));
//
                    this.richTextBox1.LoadFile(path, RichTextBoxStreamType.RichText);
                    this.richTextBox1.ReadOnly = true;
                }
                catch (Exception ee)
                {
                    Console.WriteLine(ee.Message);
                }
  

            }
        }
Posted
Comments
S@53K^S 8-Apr-13 16:13pm    
Did you try creating a global string variable and send the content of the file to that variable?
Luci C 8-Apr-13 16:14pm    
i have formatted text and images in the file... And sometimes files get bigger than 100 mb..
I don't know if all my code is correct
S@53K^S 8-Apr-13 16:24pm    
How are you planning to dump all the binary data into a richtextbox if it is mixed like images and text ? and the trick is to run progress bar in separate thread and do all the file reading and assigning to rich text box on the main thread
Luci C 8-Apr-13 16:26pm    
reading it's done very well with "Load file" method, but i do not know how can I animate the progressbar while it loads the file...
so I thought I have to put it into memory and then send it to the richtextbox..
Alan N 8-Apr-13 18:50pm    
As no one else has asked I will. Why do you
1) Read the file into a memorystream 100 times and then do nothing with it
2) Copy the RichTextBox.Text to a variable 100 times
3) Load the RichTextBox directly from the file 100 times

TPL is the easest:

XML
Task<FxMaintenanceChildViewModel> task = Task.Factory.StartNew<strReturn>((stateObj) =>
    {
        // Get the data here
        return strReturn;
    }, null);
task.ContinueWith(rtn =>
    {
       //put string into 
       richTextBox1.Text = rtn;
    }, UiScheduler);
 
Share this answer
 
Comments
Luci C 8-Apr-13 16:23pm    
didn't understand too much... so you say i must run tasks in parallel
Clifford Nelson 8-Apr-13 17:14pm    
What happens is that the first part would read the text into memory, the second continues after the task has completed, and, if you are on the UI thread when you start, you will be on the UI thread when the task completes. Besides possilby Async, this is actually quite easy.
Luci C 8-Apr-13 17:22pm    
ok, understood...but what are these "FxMaintenanceChildViewModel"and UIScheduler?
what do I have to include?
Clifford Nelson 8-Apr-13 22:29pm    
Forgot to clean that stuff out. Just replace with var. Should have been strReturn
The problem is here:
C#
this.richTextBox1.LoadFile(path, RichTextBoxStreamType.RichText);
this.richTextBox1.ReadOnly = true;


These two lines should be in a method invoked via System.Windows.Forms.Control.Invoke.

You cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Windows.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).

You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

See also more references on threading:
How to get a keydown event to operate on a different thread in vb.net[^],
Control events not firing after enable disable + multithreading[^].

Also, previous two lines make no sense. Your invoked method does nothing, and you read the content of the file stream to memory stream, which makes no sense. You really need a string to be assigned to the string property RichTextBox.Rtf, so you need to read to the char[] buffer, convert it to string and assign.

Besides, the whole activity with the thread won't help you to avoid some UI freezing much, because most of the time will be spent not on reading of the file, but on the assignment of Rtf value to the control, as the changes should be rendered. So, practically, it would be better to read the RTF file by the control itself in the UI thread.

—SA
 
Share this answer
 
Comments
Luci C 8-Apr-13 16:44pm    
Now, I thought this will be simple but it getting harder and harder:
My real situation is like this:
Form 1 is MDIParent and it show up Form2 which is an mdichild. On the Form2 I have a link-> which opens Form3 with some content read from file.
Now I want to display a progress bar on the first form while all the reading is done, and when it's complete, make the progressbar disappear and show the form3 as an mdichild

Can you explain a little more simpler what do I have to do? I am stiil at the beginning with C# and my English is not the best..

Thank you
Sergey Alexandrovich Kryukov 8-Apr-13 16:49pm    
That will be even harder and would make less sense. You cannot control the progress of rendering of Rtf, unfortunately, and the reading time, which you can really track, might be much faster...
Besides, never use MDI. Just don't.... (please see Solution 3).

Here what I think: your real problem is using RTF in general (it's pretty much obsolete), and such big size does not look reasonable to me. Why?
Please understand this: you are stress-loading your UI thread too much, you cannot do much about it. There is no such thing as miracle.

One more idea: you can use WPF instead. WPF has separate threads for UI itself and rendering. The UI will respond to RTF loading will pretty fast, but the user will experience delay trying to scroll down immediately after, but this does not happen only, because most people start from staring at the first pages. Do you see the point? In WPF this mechanism is already implemented...

—SA
Luci C wrote:
Form 1 is MDIParent and it show up Form2 which is an mdichild. On the Form2 I have a link-> which opens Form3 with some content read from file.
Here is the idea: who needs MDI, ever? Why torturing yourself and scaring off your users?
Do yourself a great favor: do not use MDI at all. You can do much easier to implement design without it, with much better quality. MDI is highly discouraged even by Microsoft, in fact, Microsoft dropped it out of WPF and will hardly support it. More importantly, you will scare off all your users if you use MDI. Just don't. Please see:
http://en.wikipedia.org/wiki/Multiple_document_interface#Disadvantages[^],
How to Create MDI Parent Window in WPF?[^].

I can explain what to do instead. Please see my past answers:
How to Create MDI Parent Window in WPF? [Solution 2],
Question on using MDI windows in WPF[^],
MDIContainer giving error[^],
How to set child forms maximized, last childform minimized[^].

—SA
 
Share this answer
 
Comments
Luci C 8-Apr-13 16:55pm    
Now my application is almost finished....I cannot reconstruct the entire solution...
Besides, it a simple one...Something more like an interactive manual.I have panel on the left which opens some other forms as mdichilds
Sergey Alexandrovich Kryukov 8-Apr-13 16:57pm    
I don't need to be negotiated about it. :-) It's all your choice, but remember that: MDI can meet quite negative acceptance. It's just not good enough these days...
And no, MDI is not so simple. Other approaches close in complexity are much simpler then MDI in implementation.
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900