据我所知,在.NET中,需要使用Control.Invoke(委托)来对控件执行操作。这让我想知道在实际需要Invoke的环境中。据我所知,在Visual Basic和Pascal的旧版本中并不需要它。特别是,Java的状态(可能依赖于版本?)和“旧式”Windows GUI编程(手动读取消息队列)是什么状态?
答案 0 :(得分:1)
你错了。 Control.Invoke不需要对控件执行操作。
Control.Invoke是一个有用的工具,可以帮助跨越线程边界编组代码,但它不是唯一的方法。当你在后台线程中做一些工作时,你会看到这种情况最常用。
当您从必须更新Windowed控件的后台线程调用代码时(即,具有Windows窗口句柄并通过消息泵处理消息的控件),更改它的属性或对控件的其他操作然后您必须将控制传递给MessagePump线程,而Control.Invoke是一种有用的方法来实现它。
在Windows下运行的 ALL 程序中,无法调用更新后台线程控件的函数。有些语言可能会在后台处理这些细节,但我不知道有什么用。
答案 1 :(得分:1)
在大多数语言中,需要调用GUI操作。在Java中有SwingUtilities.invokeLater。实际上,如果使用多个线程,在任何环境中都需要这样的方法。原因是主UI线程运行事件通知机制。能够与此机制交互的第二个线程需要以某种方式与其同步。
这些调用方法实际上对开发人员来说很方便。在不存在的平台中,并不意味着允许从不同的线程访问UI项目。这可能只意味着开发人员应该实现自定义机制(发送事件)来执行此操作。 UI代码很少是线程安全的。我使用过许多平台和技术,我一直遵循这条规则:只从单个线程触摸UI。
答案 2 :(得分:1)
Invoke只是Win32 API PostMessage的包装器。只允许拥有窗口的线程访问该窗口。当Windows是单线程时,这一直是遗留下来的。这意味着PostMessage是在Windows上访问真实窗口的正确方法,无论您使用什么(VB6,Delphi,.NET或其他),但不同的编程语言提供了包装器,使我们的生活更轻松。
答案 3 :(得分:0)
实际上,不。只有当你的GUI运行超过1个线程时才需要它。使用WinForm(和WPF)应用程序,GUI在单线程STA线程上运行(这可以追溯到COM并且不会问我为什么会这样,因为我真的不知道)。
如果您尝试从另一个线程调用在STA线程上创建的对象,则会进行检查以确保抛出异常。 WPF虽然如此,但WPF使这更加优雅。
无论如何,您实际上可以检查何时需要Invoke,因为它有一个属性。建议使用此模式来帮助处理WinForm应用程序中的多个线程。
public void MyTextSetMethod(string text)
{
if(control.InvokeRequired)
{
control.Invoke(new Action<string>(MyTextSetMethod), text);
}
else
{
control.Text = text;
}
}
上面的代码提供了一个用于设置Text属性的全方位方法,您可以根据自己的需要定制它。