线程安全控制 - 崩溃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年我在想,也许它与做将它添加到表单时设置初始文本属性,但不确定。
对我可能会做错什么或者我可能会错过什么想法?
如果不清楚,请询问。
谢谢!
答
由于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崩溃)。你的二传手也一样。
你会得到什么例外? – Clyde 2009-07-09 15:02:21
`StackOverflowException`。 – SLaks 2009-07-09 15:20:10