在这篇文章中:
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以及之后:
扩展方法通常是要走的路,因为您总是希望在ISynchronizeInvoke
接口实现上执行操作,这是一个很好的设计选择.
您还可以利用匿名方法(闭包)来解释您不知道要传递给扩展方法的参数的事实; 关闭将捕获所需的一切状态.
// 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
委托的一部分传递.
在C#3.0之前:
你没有lambda表达式的奢侈,但你仍然可以概括代码.它几乎相同,但不是扩展方法:
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)使用lambda表达式(由其他人概述).
编辑:我应该提到我不会认为这是最佳做法
如果使用的是3.5,则可以使扩展方法达到以下效果:
public static void SafeInvoke(this Control control, Action handler) { if (control.InvokeRequired) { control.Invoke(handler); } else { handler(); } }
这基本上是从:这里
然后像这样使用它:
textBox1.SafeInvoke(() => .... );
当然,请修改扩展名等以供您使用。