views:

124

answers:

4

I understand that in .NET, one needs to use Control.Invoke(delegate) to perform operations on a control. This lead me to wondering in which environments Invoke is actually required. As far as i know, it was not required in older versions of, say, Visual Basic and Pascal. In particular, what is the status of Java (possibly version-dependent?) and "old style" windows GUI programming (manually reading the message queue)?

A: 

Actually, NO. It's only needed if you're GUI is running more than 1 thread. With WinForm (and WPF) applications the GUI is running on a single threaded STA thread (this dates back to COM and don't ask me why it's like that, because I don't honestly know).

If you try to call objects created on the STA thread from a different thread, there are checks in place to make sure an exception is thrown. This same goes with WPF although, WPF makes this a lot more elegant.

Anyway, you can actually check when Invoke is required because there's a property for that. This pattern has been suggested to help with handling several threads in WinForm applications.

public void MyTextSetMethod(string text)
{
    if(control.InvokeRequired)
    {
        control.Invoke(new Action<string>(MyTextSetMethod), text);
    }
    else
    {
        control.Text = text;
    }
}

The above code provides a all around method for setting the Text property, you can tailor this to suit your needs.

John Leidegren
This has nothing to do with STAthread or not. It's true, STAthread is related to COM, but only for interop purposes. Windows requires that updates to a control happen on the same thread as the thread that created it, STA or MTA, doesn't matter.
Mystere Man
+1  A: 

You are mistaken. Control.Invoke is not required to perform operations on a control.

Control.Invoke is a useful tool to help marshall code across thread boundaries, but it is not the only way to do it. You will see this used most often when you do some work in a background thread.

When you call code from a background thread that must update a Windowed control (that is, a control that has a Windows window handle and processes messages via message pump), change it's properties, or some other manipulation of the control then you must pass control to the MessagePump thread, and Control.Invoke is a useful way to acocmplish that.

In ALL programs that run under Windows, you cannot call functions that update controls on a background thread. Some languages may handle this detail in the background, but I don't know of any that do.

Mystere Man
+1  A: 

In most languages Invoke for GUI operations is necessary. In Java there is SwingUtilities.invokeLater. Actually a method like that would be necessary in any environment if more than one threads are used. The reason is that the main UI thread runs an event notification mechanism. A second thread to be able to interact with this mechanism needs somehow to be synchronized with it.

These invoke methods are actually a convenience for the developer. In platforms that do not exist, it doesn't mean that is allowed to access UI items from a different thread. It may just means that the developer should implement a custom mechanism (sending events) to do so. UI code is very rarely thread safe. I have worked with many platforms and technologies and I am always following this rule: touch the UI from a single thread only.

kgiannakakis
+1  A: 

Invoke is just a wrapper around the Win32 API PostMessage. Only the thread that owns a window is allowed to access the window. This is legacy going all the way back to when Windows was single threaded. That means that PostMessage is the correct way to access a true window on Windows no matter what you are using (VB6, Delphi, .NET, or whatever), but the different programming languages provide wrappers to make life easier for us.

Jakob Christensen