2009-02-26 33 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或其他),但是不同的編程語言提供了包裝來讓我們的生活更輕鬆。

相關問題