CSharp - 将线程安全访问方法写入 Windows 窗体控件的最短方法

http://msdn.microsoft.com/en-us/library/ms171728(VS.80).aspx

对Windows窗体控件进行线程安全调用的模式:


private void SetText(string text)
{
 // InvokeRequired required compares the thread ID of the
 // calling thread to the thread ID of the creating thread.
 // If these threads are different, it returns true.
 if (this.textBox1.InvokeRequired)
 { 
 SetTextCallback d = new SetTextCallback(SetText);
 this.Invoke(d, new object[] { text });
 }
 else
 {
 this.textBox1.Text = text;
 }
}

有没有更短的方法来完成相同的事情(短于这个代码的长度)?

时间:

C#3.0及更高版本:


// Extension method.
static void SynchronizedInvoke(this ISynchronizeInvoke sync, Action action)
{
 // If the invoke is not required, then invoke here and get out.
 if (!sync.InvokeRequired)
 {
 // Execute action.
 action();

 // Get out.
 return;
 }

 // Marshal to the required context.
 sync.Invoke(action, new object[] { });
}

然后你可以这样调用它:


private void SetText(string text)
{
 textBox1.SynchronizedInvoke(() => textBox1.Text = text);
}

在这里,闭包位于text参数之上,状态被捕获,并作为Action委托的一部分传递给扩展方法。

在- 3.0之前:


static void SynchronizedInvoke(ISynchronizeInvoke sync, Action action)
{
 // If the invoke is not required, then invoke here and get out.
 if (!sync.InvokeRequired)
 {
 // Execute action.
 action();

 // Get out.
 return;
 }

 // Marshal to the required context.
 sync.Invoke(action, new object[] { });
}

然后使用匿名方法语法调用它:


private void SetText(string text)
{
 SynchronizedInvoke(textBox1, delegate() { textBox1.Text = text; });
}

1)使用匿名委托


private void SetText(string text)
{
 if (this.InvokeRequired)
 { 
 Invoke(new MethodInvoker(delegate() {
 SetText(text);
 }));
 }
 else
 {
 this.textBox1.Text = text;
 }
}

2)AOP方法


[RunInUIThread]
private void SetText(string text)
{
 this.textBox1.Text = text;
}

http://weblogs.asp.net/rosherove/archive/2007/05.aspx?PageIndex=2

如果使用3.5,你可以使扩展方法达到以下效果:


public static void SafeInvoke(this Control control, Action handler) {
 if (control.InvokeRequired) {
 control.Invoke(handler);
 }
 else {
 handler();
 }
}

在这里!

然后像这样使用它:


textBox1.SafeInvoke(() => .... );


public static T SynchronizedFunc<T>(this ISynchronizeInvoke sync, Func<T> func)
{
 if (!sync.InvokeRequired)
 {
 // Execute the function
 return func();
 }

 // Marshal onto the context
 return (T) sync.Invoke(func, new object[] { });
}

我最近使用这种方法以线程安全的方式获取窗体的句柄。


var handle = f.SynchronizedFunc(() => f.Handle);

...