线程安全控制 - 崩溃VS 2008

问题描述:

我正在为我的Windows窗体应用程序创建线程安全控件。线程安全控制 - 崩溃VS 2008

我明白我可以设置通过使用下面的代码安全上的控制线程的文字:

private delegate void SetTextD(Control control, string value); 

private static void SetText(Control control, string value) 
{ 
    if(control.InvokeRequired) 
    { 
     control.Invoke(new SetTextD(SetText), new object[] {control, value}); 
    } 
    else 
    { 
     control.Text = value; 
    } 
} 

然后在我的表单代码我可以打电话:

SetText(lblStatus, "Updating..."); 

我的目标是创建自定义控件,继承Label。那么这个类里面,在Text属性我可以叫:

lblStatus.Text =“更新...”

然后,它会自动地做正确的线程安全的代码。

下面是我在我的类代码:

public class ThreadSafeLabel : Label 
{ 
    private delegate string GetTextD(); 
    private delegate void SetTextD(string value); 

    private string GetText() 
    { 
     if (InvokeRequired) 
     { 
      return (string)Invoke(new GetTextD(GetText)); 
     } 
     return Text; 
    } 

    private void SetText(string value) 
    { 
     if(InvokeRequired) 
     { 
      Invoke(new SetTextD(SetText), new object[] {value}); 
     } 
     else 
     { 
      Text = value; 
     } 
    } 

    public override string Text 
    { 
     get 
     { 
      return GetText(); 
     } 
     set 
     { 
      SetText(value); 
     } 
    } 
} 

现在,当我尝试将此控件添加到我的形式,它崩溃VS 2008年我在想,也许它与做将它添加到表单时设置初始文本属性,但不确定。

对我可能会做错什么或者我可能会错过什么想法?

如果不清楚,请询问。

谢谢!

+1

你会得到什么例外? – Clyde 2009-07-09 15:02:21

+0

`StackOverflowException`。 – SLaks 2009-07-09 15:20:10

由于C#3.0的匿名方法,您不需要单独设置和获取方法。做你要找的最简单的方法是这样的:

public class ThreadSafeLabel : Label { 
    public override string Text { 
     get { 
      return InvokeRequired ? Invoke(new Func<string>(() => base.Text)) : base.Text; 
     } 
     set { 
      if (InvokeRequired) 
       BeginInvoke(new Action(() => base.Text = value)); 
      else 
       base.Text = value; 
     } 
} 

请注意,我使用BeginInvoke使调用线程不会等待调用完成;您可能需要将其更改为Invoke

编辑

与您的代码的问题是,你的set和get方法被再次调用您的重写Text财产,创造一个infinte循环,导致堆栈过低(例外,而不是网站) 。您需要编写base.Text以调用基类的Text属性的实现。

尝试

return base.Text; 

或者你会遇到一个无限循环(当您添加标签到窗体的文本属性进行查询 - 和无限循环,使VS崩溃)。你的二传手也一样。