[英]WinForms interthread modification
每当我想从另一个线程修改winform时,我需要使用
->Invoke(delegate, params)
以便修改发生在winform自己的线程中。
对于需要修改gui的每个函数,我需要另一个委托函数。
是否有一些方案允许我限制所需的委托功能的数量? 我有一个控制器类,可以在一个地方处理整个gui,我考虑过重用代表但是闻起来很糟糕。
我认为我的问题可以适用于winform可以运行的所有语言
如果您使用的是C#3,则可以使用lambda,而在C#2中,则使用匿名委托。 当不需要重用行为时,这些简化了语法。 我经常做的一件事是在表单代码中进行同步,而不是在控制器中进行。 控制器不应该受到这种技术更具体的“管道”问题的困扰,而不是控制器逻辑。
public void ResetFields()
{
// use "delegate" instead of "() =>" if .Net version < 3.5
InvokeOnFormThread(() =>
{
firstInput.Text = Defaults.FirstInput;
secondInput.Text = Defaults.SecondInput;
thirdChoice.SelectedIndex = Defaults.ThirdChoice;
});
}
// change Action to MethodInvoker for .Net versions less than 3.5
private void InvokeOnFormThread(Action behavior)
{
if (IsHandleCreated && InvokeRequired)
{
Invoke(behavior);
}
else
{
behavior();
}
}
作为一种做法,使表单中的所有公共方法调用“InvokeOnFormThread”。 或者,您可以使用AOP拦截表单上的公共方法调用并调用“InvokeOnFormThread”,但上面已经运行得很好(如果您保持一致并记住总是在窗体或UserControls上的公共方法上执行)。
看看使用现有的System.Action<T>
和System.Func<T,T>
委托:
control.Invoke(
new Action<int, string>(
(i, s) => MessageBox.Show(String.Format(s, i))), 1, "{0}");
int iret = (int) control.Invoke(new Func<int, int>(i1 => i1 + 1));
Michael Meadows的答案是如何集中更新GUI表单逻辑的一个很好的例子。
关于调用众多代表来同步前端的性能(我们很容易被痴迷),不久之前,我编写的软件在GUI同步方面优于同等的C ++(本机)Windows应用程序! 这完全归功于BeginInvoke
和ThreadPool
类。
使用Action<>
和Func<>
委托和ThreadPool
类也是有益的,并考虑一般的Invoke
模式(由上面的Michael公开):
public void TheGuiInvokeMethod(Control source, string text)
{
if (InvokeRequired)
Invoke(new Action<Control, string>(TheGuiInvokeMethod, source, text);
else
{
// it is safe to update the GUI using the control
control.Text = text;
}
}
其中TheGuiInvokeMethod
确实位于表单或其他控件中。
我记得关闭检查并手动验证我使用的每个电话都是安全的。
由于我保证了某些线程的位置(信号量),或者因为它们调用了可以在其他进程上使用的底层API函数,因此可以将其中令人惊讶的数量称为交叉线程。
我最终仍然有很多调用,通常是在上下文对象上,所以我可以使用MethodInvoker。
我还在Control.Invoke中遇到了一个令人讨厌的错误,驱使我写一个自定义调用程序库。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.