http://blog.csdn.net/xiaochongchong1248/archive/2009/11/20/4841193.aspx?1271573283
编程环境要求:VS2008/FX2.0
众所周知,从VS2005/FX2.0起,在多线程环境下是不允许跨线程修改主线程上窗口控件的。
private
void
button1_Click(
object
sender, EventArgs e)
Thread t
=
new
Thread(
new
ThreadStart(CrossThreadCall));
t.Start();
}
public
void
CrossThreadCall()
Text
=
"
test
"
;
将直接导致异常:
未处理 System.InvalidOperationException
Message="线程间操作无效: 从不是创建控件“Form1”的线程访问它。"
Source="System.Windows.Forms"
StackTrace:
在 System.Windows.Forms.Control.get_Handle()
在 System.Windows.Forms.Control.set_WindowText(String value)
在 System.Windows.Forms.Form.set_WindowText(String value)
在 System.Windows.Forms.Control.set_Text(String value)
在 System.Windows.Forms.Form.set_Text(String value)
在 delegate_test1.Form1.CrossThreadCall() 位置 f:\app\delegate_test1\delegate_test1\Form1.cs:行号 26
在 System.Threading.ThreadHelper.ThreadStart_Context(Object state)
在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
在 System.Threading.ThreadHelper.ThreadStart()
通用的解决方法是使用Control.Invoke方法来调用一个Delegate,从而安全地跨线程调用。
public
void
CrossThreadCall()
Invoke(
new
void_d(CrossThreadCall_Local));
}
void
CrossThreadCall_Local()
Text
=
"
test
"
;
}
public
delegate
void
void_d();
但是这样的缺点是要不得不为每个调用编写一个Invoke跳板,还要额外声明一个委托类型,实在不怎么优雅。
于是我们想到用匿名函数来写。我的第一反应是:
Invoke(
delegate
{ Text
=
"
test
"
; });
可惜不行。编译压根就没通过,写着:
无法将 匿名方法 转换为类型“System.Delegate”,因为它不是委托类型
无语,delegate竟然不是委托类型?
等我把Google翻了一遍后,找到了答案。
The problem the user is seeing is that the Thread ctor accepts a specific delegate -- the ThreadStart delegate. The C# compiler will check and make sure your anonymous method matches the signature of the ThreadStart delegate and, if so, produces the proper code under-the-covers to create the ThreadStart delegate for you.
But Control.Invoke is typed as accepting a "Delegate". This means it can accept any delegate-derived type. The example above shows an anonymous method that has a void return type and takes no parameters. It's possible to have a number of delegate-derived types that match that signature (such as MethodInvoker and ThreadStart -- just as an example). Which specific delegate should the C# compiler use? There's no way for it to infer the exact delegate type so the compiler complains with an error.
也就是说,对于Thread.ctor()来说,由于接受的是一个ThreadStart委托,编译器便可以将匿名函数与ThreadStart委托类型匹配,最后能够正确编译。
而对于Control.Invoke()来说,任何的代理类型都是可接受的,也就是说ThreadStart和MethodInvoker都是可以接受的类型。这样编译器反而不知道应该用哪个代理去匹配匿名函数了,导致了编译错误的发生。
知道了原因,问题就很容易解决了。我们只需要加上MethodInvoker这个wrapper就能使用匿名函数了。
Invoke(
new
MethodInvoker(
delegate
{ Text
=
"
test
"
; }));
或者更简单地,用Lambda表达式来解决问题:
Invoke(
new
MethodInvoker(()
=>
Text
=
"
test
"
));
希望本文能够帮助有同样困惑的朋友。
本文转自火地晋博客园博客,原文链接:http://www.cnblogs.com/yelaiju/archive/2010/09/16/1827691.html,如需转载请自行联系原作者
C#委托/Func()中 GetlnvocationList()方法的使用 | 接受委托多个返回值
C#委托/Func()中 GetlnvocationList()方法的使用 | 接受委托多个返回值
总觉得之前第2处有点问题,果然.
还需要instanceof判定一下,然后还需要把数组Animal[]转为Pet的才有方法play()~~~!将编程看作是一门艺术,而不单单是个技术。
敲打的英文字符是我的黑白琴键,
思维图纸画出的是我编写的五线谱。