How to update a RichTextBox from BackgroundWorker using BeginInvoke
Solution 1
You need an else
statement in your the UpdateResultsLine
method. When Invoke
is required, you are executing the UpdateResultsLine
method using the delegate (invoking), but then you call again without using Invoke
Also, why do you use BeginInvoke
(async) and use Invoke
(sync)? Are you sure you have no sync problems? Using Invoke and adding an else statement could solve your problems:
private void UpdateResultsLine(string line, List<char> foundChars)
{
if (txtResults.InvokeRequired)
{
txtResults.Invoke(
new UpdateResultsLineDelegate(UpdateResultsLine),
line,
foundChars);
}
else
{
txtResults.AppendLine(
line,
foundChars,
_fileType.ProcessColumns);
}
}
Solution 2
Here what you can try, create the extension class as follows
public static class ControlExtensions
{
public static void Invoke(this Control control, Action action)
{
if (control.InvokeRequired) control.Invoke(new MethodInvoker(action), null);
else action.Invoke();
}
}
And when ever and where ever you want to update anything on UI, you just need to do
richTextBox.Invoke(() => { richTextBox.AppendText(text + Environment.NewLine); });
Hope this works for you.
BlueChippy
Updated on June 05, 2022Comments
-
BlueChippy almost 2 years
I have a small app that reads in a pipe delimted file and writes out lines to a RTB, highlighting if there are dissallowed characters in certain "columns". This is working perfectly...however, the Users want a progress bar and to see the lines being written "live" and also to be able to cancel mid-way through.
I have the following extension method that I have been using to write to a RichTextBox, while blocking the UI, but this fails using a BackgroundWorker with BeginInvoke.
The fail is when finding the current length of the text.
public static void AppendLine(this RichTextBox richTextBox, string text, List<Char> foundChars, List<int> columns) { var split = text.Trim().Split(new char[] { '|' }); for (int i = 0; i < split.Count(); i++) { **var start = richTextBox.TextLength;** richTextBox.AppendText(split[i]); var end = richTextBox.TextLength; if (columns.Contains(i + 1)) { foreach (var foundChar in foundChars) { var current = start; while (current > 0) { var position = richTextBox.Find(new char[] { foundChar }, current, end); current = position + 1; if (current > 0) { richTextBox.Select(position, 1); richTextBox.SelectionColor = Color.Red; } } } } richTextBox.SelectionLength = 0; richTextBox.SelectionColor = Color.Black; } richTextBox.AppendLine(); }
private void UpdateResultsLine(string line, List<char> foundChars) { if (txtResults.InvokeRequired) { txtResults.BeginInvoke(new UpdateResultsLineDelegate(UpdateResultsLine), line, foundChars); } txtResults.AppendLine(line, foundChars, _fileType.ProcessColumns); }
However, if I call any/all of these extensions in the same way, they work?
public static void AppendLine(this RichTextBox richTextBox) { richTextBox.AppendText(Environment.NewLine); } public static void AppendLine(this RichTextBox richTextBox, string text) { richTextBox.AppendText(text + Environment.NewLine); } public static void AppendLine(this RichTextBox richTextBox, string text, params object[] args) { richTextBox.AppendLine(string.Format(text, args)); }
What am I missing? or is there another way to write coloured text to a RTB?
-
BlueChippy over 12 yearsI'd got half way by adding the "else" clause, but BeginInvoke -> Invoke sorted the rest for me. Thx
-
BlueChippy over 12 yearsDaniel answered first and I implemented his solution so he gets the points...however I might switch to this one as I like the clarity.
-
Kiquenet almost 12 yearsMaybe better BeginInvoke kristofverbiest.blogspot.com/2007/02/…
-
Sheikh M. Haris over 8 yearsPerfect solution for my case, as I have to update current progress in Rich Text Box. Thanks
-
Admin over 5 yearsit also works with adding an item in a listbox --> myListBox.Invoke( ( ) => { myListBox.Items.Add( myListOfStrings[ i ] ); } );