本想翻译来着,后来想想算了,一是比较懒,二是没时间,三是觉得没必要。有需要的话评论原文地址:http://kristofverbiest.blogspot.sg/2007/02/simple-pattern-to-invoke-gui-from.html
Let me first say that although this seems to be an annoyance for the developer, this is actually a great thing! It means that while you are developing a GUI application you generally don't have to worry about threading issues (locks, deadlocks) because you know that all GUI-access is done from a single thread.
But of course there are situations where you want to start background processing on a seperate thread and access the GUI from this thread. Take for instance this simple example:
If you call this method from a thread that is not a GUI thread, everything may seem to go well at first sight. But because we violated the very important rule, the behaviour of our application is now undefined. Things may (and will) start to go wrong very unpredictably, sometimes much later when there is no obvious relationship with the violation that was made. This makes this problem very hard to find. Among the things that could happen is GUI-events to become 'lost' and the GUI to become unresponsive.
Luckily, form Visual Studio 2005 onward you get a nice error-message when you violate this rule while the debugger is attached:
So now you at least get an immedeate notification that you made a mistake. This one of the reasons why I advise to run your code from Visual Studio (using F5) while you are developing.
To get around our threading-violation, Winforms provides these helper-methods: BeginInvoke, EndInvoke, Invoke, InvokeRequired. But even with these methods available it may not be obvious how to use them in a correct and simple way.
That's why I present this pattern:
As you can see, you will need to define a delegate that matches your method (or use an existing delegate that is defined elsewhere, such as the System.Windows.Forms.MethodInvoker). This is how the pattern works:
This is in my opinion the simplest and shortest pattern that is always correct.
From .NET 2.0 onwards the same pattern can be written using an anonymous method but that is less readable in my opinion, so I prefer to keep this pattern.
Also in .NET 2.0 you can use the BackgroundWorker class that handles all the details behind your back. But the same principle still applies: never access GUI from another thread!
第一条评论的方法也可以:
I prefer a small helper class like this one, it makes the code even cleaner and shorter:
using System.Windows.Forms;
public static class ControlsHelper
{
public static void SyncBeginInvoke(control, MethodInvoker del)
{
if ((control != null) && control.InvokeRequired)
control.BeginInvoke(del, null);
else
del();
}
}
private void SetLabelText(int number)
{
ControlsHelper.SyncBeginInvoke(this, delegate()
{
label.Text = number.ToString();
});
}