1

In the following code MessageReceived is on a different thread to label1 and when trying to access it I will get this error:

Cross-thread operation not valid: Control 'label1' accessed from a thread other than the thread it was created on.

foo.MessageReceived += new Agent.MessageReceivedHandler(foo_MessageReceived); 

void foo_MessageReceived(Message message)
{
   label1.Text = message.Body;
}    

How can I solve this?

More: apparently I need to use delegate and invoke, but I don't know how, can you please explain in more detail?

Ali
  • 5,286
  • 9
  • 33
  • 36
  • 1
    Exact duplicate (not NPR, as I mistakenly clicked): http://stackoverflow.com/questions/244591 http://stackoverflow.com/questions/142003 http://stackoverflow.com/questions/470390 amongst others. – Jon Skeet Mar 03 '09 at 14:52

6 Answers6

4

Hopefully this will be closed as an exact duplicate, but if not:

Don't touch the GUI from a non-GUI thread. Use BackgroundWorker and report progress appropriately, or read the WinForms page of my threading article for more direct control (Control.Invoke/BeginInvoke).

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
1

Delegate updating the label to the thread that created the label instead of trying to update it directly.

Welbog
  • 59,154
  • 9
  • 110
  • 123
1

You need to use Control.Invoke (or Control.BeginInvoke). First, create a new Windows Forms application and add a label and a button. Double click on the button in Visual Studio to edit it's Click event and add the following code:

    private void button1_Click(object sender, EventArgs e)
    {
        new System.Threading.Thread(new System.Threading.ThreadStart(Run)).Start();
    }

    void Run()
    {
        label1.Invoke(new Action(delegate()
        {
            label1.Text = System.Threading.Thread.CurrentThread.Name + " " + System.DateTime.Now.ToString();
        }));
    }
Joe Erickson
  • 7,077
  • 1
  • 31
  • 31
0

This is totally not helpful. I wish I could vote myself down.

I may be out of date, but from what I remember you aren't allowed to alter anything in the GUI from anything but the main thread.

Restore the Data Dumps
  • 38,967
  • 12
  • 96
  • 122
0

In your Agent class, when you raise the MessageReceived event, you'll have to check whether the Target of the event-handler implements ISynchronizeInvoke. If it does, and if the InvokeRequired property returns true, you'll have to invoke the eventhandler.

If you're not using WinForms, but WPF, you cannot rely anymore on ISynchronizeInvoke since the WPF controls do not implement that interface. Instead, you'll have to work with AsyncOperation and AsyncOperatoinManager.

Frederik Gheysels
  • 56,135
  • 11
  • 101
  • 154
0

Make always sure you update your GUI on the main thread (GUI thread).

foo.MessageReceived += new Agent.MessageReceivedHandler(foo_MessageReceived);

public delegate void MyDelegate(Message msg);
void foo_MessageReceived(Message message)
{ 
   if (InvokeRequired)
   {
      BeginInvoke(new MyDelegate(foo_MessageReceived),new object[]{message});
   }
   else
   {
      label1.Text = message.Body;
   }
}
Chinmaya003
  • 474
  • 3
  • 10
Mez
  • 2,817
  • 4
  • 27
  • 29