-1

I am trying to code something that retrieves and parses the HTML of a site. I am successful on that but when I try to put it into a rich textbox using a background worker I get a cross-thread exception.

List<string> retuInfo = new List<string>();
foreach (var inf in info)
{
       retuInfo.Add(inf.InnerText);
       richTextBox1.Lines = retuInfo.ToArray();
}

I get the exception on richTextBox1.Lines = retuInfo.ToArray();

I have looked at several things on "Unsafe threading and safe threading" but none of it really helped as threading is a pretty advanced topic and can throw some hard bugs at you.

Any possible help?

Soner Gönül
  • 91,172
  • 101
  • 184
  • 324
John
  • 73
  • 7
  • 6
    We've had this a million times here... Invoke is the keyword. – jAC May 02 '13 at 07:52
  • 1
    You can also take a look at [SynchronizationContext](http://www.codeproject.com/Articles/31971/Understanding-SynchronizationContext-Part-I) class. – ahawkthomas May 02 '13 at 07:54
  • 1
    In which method you are using this code? Write the logic in the ProgressChanged method if you are accessing any UI method and call it using ReportProgress method. – sohail.hussain.dyn May 02 '13 at 07:56

2 Answers2

1

When you update UI control you should call from UI thread instead of you update from Backgroundworker thread. To call Ui thread you should use Invoke or BeginInvoke to call thread UI update on Richtextbox control.

You can take reference here:

Invoke(Delegate)

or

Parallel Programming using TPL on WinForms

Community
  • 1
  • 1
Toan Vo
  • 1,251
  • 9
  • 19
  • So I am checking out the second link you gave me there and I tried this still getting some errors and its a bit a confusing but am I on the right track? List retuInfo = new List(); richTextBox1.Invoke(new Action(()richTextBox1.Lines = retuInfo.ToArray()); – John May 02 '13 at 08:22
  • Fixed it no error this time except nothings happening now?richTextBox1.Invoke(new Action(() => richTextBox1.Lines = retuInfo.ToArray())); – John May 02 '13 at 08:35
  • Aye! It worked sorry I realized I did not put back the foreach thing it's been a long day of everyday things and a long night of coding. I really appreciate this with helping me better understand and learn guys. I really appreciate and honestly wish I could put both for best answer -.- – John May 02 '13 at 08:43
  • Good job John. Glad to see you can resolve it by yourself. – Toan Vo May 02 '13 at 08:45
  • One more thing can you explain to me how richTextBox1.Invoke(new Action(() => richTextBox1.Lines = retuInfo.ToArray())); worked?I dont understand the "new Action and =>" – John May 02 '13 at 08:45
  • the new Action()=> .. actually is create a new anonymous delegate. Take reference here. http://msdn.microsoft.com/en-us/library/018hxwa8%28v=vs.100%29.aspx – Toan Vo May 02 '13 at 08:47
  • You can take reference at here to learn how to use and get benefit from it instead of using directly delegate syntax. http://stackoverflow.com/questions/371054/uses-of-action-delegate-in-c-sharp – Toan Vo May 02 '13 at 08:54
1

In your form define a method that will append the lines to the control:

public void SetRichTextBoxText(string[] lines)
{
    if(!richTextBox1.InvokeRequired)
    {
        richTextBox1.Lines = lines;
    }
    else
    {
        var callback = new Action<string[]>(SetRichTextBoxText);
        Invoke(callback, lines);
    }
}

In your background worker call the method like this:

form.SetRichTextBoxText(info.Select(inf => inf.InnerText).ToArray());
RePierre
  • 8,782
  • 2
  • 20
  • 35