线程安全控制 - 崩溃VS 2008

时间:2009-07-09 14:57:38

标签: c# visual-studio-2008 custom-controls

我正在为我的Windows窗体应用程序创建一个线程安全控件。

我知道我可以使用以下代码将控件线程上的文本设置为安全:

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.我在想,也许它与将初始文本属性添加到表单时设置初始文本属性有关,但不确定。

关于我可能做错了什么或者我可能错过什么的任何想法?

如果不清楚,请询问。

谢谢!

2 个答案:

答案 0 :(得分:2)

尝试

return base.Text;

或者您将遇到无限循环(当您将Label添加到表单时,将查询Text-property - 并且无限循环会导致VS崩溃)。你的二传手也一样。

答案 1 :(得分:1)

由于C#3.0的匿名方法,您不需要单独的set和get方法。做你正在寻找的最简单的方法是这样的:

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属性的基类实现。