我们目前有一个从串行通信中读取数据的应用程序。在整个应用程序中,我们需要在UI中显示这些数据,因此我们创建了一个使用BeginInvoke更新文本框/标签/数字/进度条的方法。
然而,这开始变得麻烦,因为每个控件都需要自己的'Setter',这样我们已经有20个左右的方法,它们基本上都是一样的。
虽然我可以看到一种简单的方法将其泛化为特定控件(例如,标签只有1个,文本框只有1个),但我们可以调用更新数据的理想选择只有1个(可能是扩展名)方法在用户界面。
以下是我们原来的方法:
private void SetCell1Cell2Async(decimal value)
{
if (spinCell1Cell2.InvokeRequired)
{
spinCell1Cell2.BeginInvoke(new EventHandler(delegate
{
spinCell1Cell2.Value = value;
}));
}
else
{
if (spinCell1Cell2.IsDisposed) return; // Do not process if the control has been disposed of
if (spinCell1Cell2.IsHandleCreated)
{
// This handle may not be created when creating this form AFTER data is already flowing
// We could capture this data for future display (i.e. via deferUpdate = true or similar), but it is easier to ignore it
// i.e. Do Nothing
return;
}
spinCell1Cell2.Value = value;
}
}
这是我们当前的方法(适用于使用Text
属性显示数据的控件):
delegate void SetTextAsyncCallback(Control ctrl, string text);
public static void SetTextAsync(this Control invoker, string text)
{
if (invoker.InvokeRequired)
{
invoker.BeginInvoke(new SetTextAsyncCallback(SetTextAsync), invoker, text);
}
else
{
if (invoker.IsDisposed) return; // Do not process if the control has been disposed of
if (!invoker.IsHandleCreated)
{
// This handle may not be created when creating this form AFTER data is already flowing
// We could capture this data for future display (i.e. via deferUpdate = true or similar), but it is easier to ignore it
// i.e. Do Nothing
return;
}
invoker.Text = text;
}
}
正如您所看到的,此方法适用于使用Text
属性显示其数据的任何内容。
理想情况下,我希望能够“传递”要更新的属性,并提供一个方法,该方法需要string
,double
,decimal
,{{1等等,但我有点失落,从这里开始。
任何帮助表示感谢。
答案 0 :(得分:2)
我会在表单中创建一个更通用的解决方案:
delegate void ActionCallback();
private void SetText()
{
this.SafeInvoke(() =>
{
if (spinCell1Cell2.IsDisposed) return;
if (!spinCell1Cell2.IsHandleCreated) return;
// Do stuff
});
}
private void SafeInvoke(ActionCallback action)
{
if (this.InvokeRequired)
this.Invoke(action);
else
action();
}
使用委托,您只需要声明实际操作一次,而稍后决定执行类型(在SafeInvoke方法中)。如果你想要一些扩展方法,这里有一个例子:
public delegate void ActionCallback();
public static void SafeInvoke(this Form form, ActionCallback action)
{
if (form.InvokeRequired)
form.Invoke(action);
else
action();
}
public static void SafeSetText(this Control ctl)
{
var form = ctl.FindForm();
if (form == null) return; // or do something else
form.SafeInvoke(() =>
{
// Do stuff
});
}
修改强> 在再次阅读你的问题后,我注意到这不是你所问的,所以我会给你一个更相关的例子:
public static void SafeUpdate<T>(this T ctl, ActionCallback action) where T : Control
{
var form = ctl.FindForm();
if (form == null) return; // or do something else
SafeInvoke(action);
}
// Then in some other method
{
textBox1.SafeUpdate(() =>
{
textBox1.Text = "123";
textBox1.ForeColor = Color.Red;
});
}