Hello all,
I'm working on an update for one of my programs, and the Load function that loads the user's information is lagging for maybe 1 or two seconds. In my application, the user can click buttons and scroll through pages. This leads to a slightly annoying
experience if the user is scrolling through the pages and the content takes a second or two to load; the scrolling will not be as seamless as I'd like it to be. In the past, this wasn't an issue because I only had 11 RichTextBoxes on the main window (and
I did it in Windows Forms). Now, I have 21 RichTextBoxes on the interface, and I can't seem to find a way to increase the loading speed.
I am fully aware of the System.Threading.Thread options; however, I want to allocate some parts of the loading code to different threads but wait for the entire process to complete before anything else happens. Using an entirely new background thread to do
the loading wouldn't work very well because the user could navigate to a new page on the UI thread, and the background thread (not having completed yet) could potentially load the previous page's information a little late, thereby leaving the user
with the wrong page information.
Here's my synchronous loading code that is running just a little slower than I'd hope it would:
TextRange RtfText; foreach (RichTextBox box in RichTextBoxList) { using (FileStream stream = new FileStream(FilePath + box.Name.Substring(3) + ".rtf", FileMode.Open, FileAccess.Read)) { RtfText = new TextRange(box.Document.ContentStart, box.Document.ContentEnd); RtfText.Load(stream, DataFormats.Rtf); } }
As you can see, I go through each RichTextBox in the list, open a file stream to the correct file name, and then load it into a TextRange. To speed this up, I thought I would use Parallel Tasks (http://msdn.microsoft.com/en-us/library/ff963549),
but it seems as though I'm still running into issues with that. I've tried using two slightly different methods to use parallel tasks:
1) Parallel.For
Parallel.For(0, 22, (i) => { LoadRTF(FilePath, RichTextBoxList[i]); } );
private void LoadRTF(String FilePath, RichTextBox box) { using (FileStream stream = new FileStream(FilePath + box.Name.Substring(3) + ".rtf", FileMode.Open, FileAccess.Read)) { TextRange RtfText = new TextRange(box.Document.ContentStart, box.Document.ContentEnd); RtfText.Load(stream, DataFormats.Rtf); } }
This unfortunately did not work, as I got the following error message:
The calling thread cannot access this object because a different thread owns it.
Using the same LoadRTF method as above, I tried a different approach to see if the results would change:
2) Task.Factory
List<Task> tasks = new List<Task>(); RichTextBox TempBox; foreach (RichTextBox box in main.TextBoxes) { TempBox = box; tasks.Add(Task.Factory.StartNew(() => LoadRTF(FilePath, TempBox))); }
Unfortunately, I still got the same error message: The calling thread cannot access this object because a different thread owns it.
A quick google search of this revealed that only the UI thread can access controls and their properties (in this case, Name). I've looked into how I could possibly change my code to accommodate this, but I haven't had any luck so far.
I am wondering if anyone could please give me some guidance on how I can speed up my RTF loading code, however it may be. If someone could assist me with changing my code to use the UI thread so that I will no longer get this persistent error message,
that would be great. If you can suggest another, working method of getting this done (even synchronously!), that'd be awesome as well.
My greatest thanks goes out to anyone who takes the time out to lend me a hand!