C# 如何以线程安全的方式更新控件

C# 如何以线程安全的方式更新控件,c#,winforms,visual-studio-2010,thread-safety,backgroundworker,C#,Winforms,Visual Studio 2010,Thread Safety,Backgroundworker,我有一个windows.form.userControl类,在运行时我想动态添加一些链接标签。当我在Load方法中应用这个代码片段时,它工作得非常好 for (int i = 0; i < 10; i++) { linkLabel = new System.Windows.Forms.LinkLabel(); linkLabel.Name = i.ToString(); linkLabel.Text = i.ToString();

我有一个windows.form.userControl类,在运行时我想动态添加一些链接标签。当我在Load方法中应用这个代码片段时,它工作得非常好

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;
      }
for(int i=0;i<10;i++)
{
linkLabel=new System.Windows.Forms.linkLabel();
linkLabel.Name=i.ToString();
linkLabel.Text=i.ToString();
linkLabel.LinkClicked+=新系统.Windows.Forms.LinkLabelLinkClickedEventHandler(linkLabel\u LinkClicked);
this.Controls.Add(linkLabel);
linkLabel.Top=Top;
top+=30;
}
但当我将此代码段移到backgroundworkerdoWork方法中时,它将给出与此行中的交叉线程问题相关的无效操作异常:-this.Controls.Add(linkLabel)

如何使其成为线程安全操作?我是C#的新手,我正在使用VS2010的C#4.0。
提前感谢。

您应该切换到创建该控件的线程,以便与之交互

使用此代码修复此问题

if(this.InvokeRequired)
   this.Invoke(new Action(() => {this.Controls.Add(linkLabel);}));
else
   this.Controls.Add(linkLabel); 

您必须将该方法与UI线程同步。您可以使用属性
Control.invokererequired
检查是否需要同步,也可以使用属性
Control.Invoke
同步调用任何委托

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;
    }
}
private void AddLinkLabels()
{
//如果需要同步,即在非UI线程上调用此方法时,调用同步的方法并立即返回。
如果(需要调用)
{
调用(新MethodInvoker(AddLinkLabels));
返回;
}
对于(int i=0;i<10;i++)
{
linkLabel=new System.Windows.Forms.linkLabel();
linkLabel.Name=i.ToString();
linkLabel.Text=i.ToString();
linkLabel.LinkClicked+=新系统.Windows.Forms.LinkLabelLinkClickedEventHandler(linkLabel\u LinkClicked);
this.Controls.Add(linkLabel);
linkLabel.Top=Top;
top+=30;
}
}

来自Stecya的答案也可以输入。

正如Stecya已经说过的:您应该切换到创建该控件的线程,以便与之交互。这可以在backgroundworkers ProgressChanged事件中完成,因为它在UI线程中工作,无需执行调用。Sample at.

我将使用整个方法调用invoke,因为您的示例将导致对
控件的十次调用。invoke
而不是一次。这是一个优化问题。你是对的,需要避免多次调用非常感谢:)嗨Florian,这行“Invoke(AddLinkLabels);”给出错误,说明参数无效。你知道吗?谢谢