2009-02-26 65 views
0

我知道在.NET中,需要使用Control.Invoke(委托)来对控件执行操作。这导致我想知道在哪些环境中Invoke实际上是需要的。据我所知,在Visual Basic和Pascal的旧版本中并不需要它。特别是,Java的状态(可能是版本依赖?)和“老式”Windows GUI编程(手动读取消息队列)的状态是什么?需要什么语言/平台调用GUI操作?

回答

1

在大多数语言中调用GUI操作是必要的。在Java中有SwingUtilities.invokeLater。实际上,如果使用多个线程,则在任何环境中都需要这样的方法。原因是主UI线程运行事件通知机制。能够与此机制交互的第二个线程需要以某种方式与其进行同步。

这些调用方法实际上是开发人员的方便。在不存在的平台中,并不意味着它被允许从另一个线程访问UI项目。这可能意味着开发人员应该实现自定义机制(发送事件)来执行此操作。 UI代码很少是线程安全的。我曾与许多平台和技术合作过,并且始终遵循以下规则:仅从单个线程触摸UI。

0

其实,只有当GUI运行多于1个线程时才需要它。使用WinForm(和WPF)应用程序,GUI在单线程STA线程上运行(这可以追溯到COM,不要问我为什么会这样,因为我不知道)。

如果您尝试从其他线程调用在STA线程上创建的对象,则会进行检查以确保引发异常。 WPF也是如此,但WPF使得这更加优雅。

无论如何,你可以实际检查何时Invoke是必需的,因为有一个属性。建议使用此模式来帮助处理WinForm应用程序中的多个线程。

​​

上述代码提供了一种设置Text属性的全方位方法,您可以根据需要对其进行定制。

+0

这与STAthread与否无关。确实,STA线程与COM相关,但仅用于互操作目的。 Windows要求对控件的更新发生在与创建它的线程相同的线程上,STA或MTA无关紧要。 – 2009-02-26 09:02:11

1

你错了。 Control.Invoke不需要在控件上执行操作。

Control.Invoke是一个有用的工具,它可以帮助编制跨线程的代码,但它不是唯一的方法。当您在后台线程中执行某些工作时,您会看到最经常使用的功能。

当您从后台线程调用必须更新Windowed控件(即具有Windows窗口句柄并通过消息泵处理消息的控件)的代码时,请更改其属性或控件的其他操作,然后您必须将控制传递给MessagePump线程,并且Control.Invoke是一种有效的方法来解决这个问题。

全部在Windows下运行的程序,您不能调用在后台线程上更新控件的函数。有些语言可能会在后台处理这些细节,但我不知道有任何问题。

1

Invoke只是Win32 API PostMessage的一个包装。只有拥有窗口的线程才被允许访问该窗口。当Windows是单线程的时候,这是遗留下来的。这意味着PostMessage是在Windows上访问真实窗口的正确方法,无论您使用的是什么(VB6,Delphi,.NET或其他),但是不同的编程语言提供了包装来让我们的生活更轻松。