3

I have a windows.form.userControl class and at run time i want to add some linklabels dynamically. When I apply this code snippet inside Load method it work perfectly.

for (int i = 0; i < 10; i++)
     {
       linkLabel = new System.Windows.Forms.LinkLabel();
       linkLabel.Name = i.ToString();
       linkLabel.Text = i.ToString();
       linkLabel.LinkClicked += new  System.Windows.Forms.LinkLabelLinkClickedEventHandler(linkLabel_LinkClicked);
       this.Controls.Add(linkLabel);
       linkLabel.Top = top;
       top += 30;
      }

But when I move this code snippet inside to backgroudworker doWork method it will give invalid operation exception related to cross thread issue in this line :- this.Controls.Add(linkLabel);

How do I make this as a thread safe operation? I'm newbie to C# and I'm using C# 4.0 using VS 2010. Thanks in advance.

djv
  • 15,168
  • 7
  • 48
  • 72
Gihan Anuruddha
  • 339
  • 4
  • 11

4 Answers4

6

You should switch to thread that created that control in order to interact with it

Use this code to fix this

if(this.InvokeRequired)
   this.Invoke(new Action(() => {this.Controls.Add(linkLabel);}));
else
   this.Controls.Add(linkLabel); 
Stecya
  • 22,896
  • 10
  • 72
  • 102
3

You have to synchronize the method to the UI thread. You can use the property Control.InvokeRequired to check if synchronization is needed and Control.Invoke to invoke any delegate synchronously.

private void AddLinkLabels()
{
    // If synchronization is needed, i.e. when this method is called on a non-UI thread, invoke the method synchronized and return immediately.
    if(InvokeRequired)
    {
        Invoke(new MethodInvoker(AddLinkLabels));
        return;
    }

    for (int i = 0; i < 10; i++)
    {
        linkLabel = new System.Windows.Forms.LinkLabel();
        linkLabel.Name = i.ToString();
        linkLabel.Text = i.ToString();
        linkLabel.LinkClicked += new  System.Windows.Forms.LinkLabelLinkClickedEventHandler(linkLabel_LinkClicked);
        this.Controls.Add(linkLabel);
        linkLabel.Top = top;
        top += 30;
    }
}
Florian Greinacher
  • 14,478
  • 1
  • 35
  • 53
1

The answer from Stecya can also be put into an extension method like this.

Community
  • 1
  • 1
Oliver
  • 43,366
  • 8
  • 94
  • 151
0

As Stecya already said: You should switch to thread that created that control in order to interact with it. This can be done in backgroundworkers ProgressChanged event, because it works in UI thread, without need to do invoke. Sample at MSDN.

VikciaR
  • 3,324
  • 20
  • 32