3

我有一个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; 
     } 

可是当我中移动这个代码片段backgroudworker的doWork方法,它会给跨线程问题,在这条线的相关操作无效异常: - this.Controls.Add(的LinkLabel);

如何将此作为线程安全操作?我是C#的新手,我使用VS 2010使用C#4.0。 在此先感谢。

回答

3

必须同步方法到UI线程的线程。您可以使用属性Control.InvokeRequired来检查是否需要同步,并使用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; 
    } 
} 
+0

嗨弗洛里安,这一行'Invoke(AddLinkLabels);'给错误说无效论点。有关于此的任何想法?谢谢。 – 2011-05-31 05:00:21

+0

@poor_guy:我更新了我的答案 – 2011-05-31 06:15:23

+0

非凡:D非常感谢:-) – 2011-05-31 07:23:53

6

你应该切换到创建的控制,以与它交互

使用此代码来解决这个

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

我会调用整个方法,因为您的示例将导致十个调用“Control.Invoke”而不是一个。 – 2011-05-30 10:48:47

+0

这是一个优化问题。你是对的,需要避免多个Invokes – Stecya 2011-05-30 10:52:32

+0

Stecya非常感谢你:) – 2011-05-30 10:59:13

0

由于Stecya已经说过:您应该切换到创建该控件的线程才能与之交互。这可以在backgroundworkers ProgressChanged事件中完成,因为它可以在UI线程中工作,而无需执行调用。样品在MSDN