原文http://www.cnblogs.com/yjmyzz/archive/2010/03/18/1689256.html
Silverlight/WPF中,如果要在多线程中对界面控件值做修改,用Dispatcher对象的BeginInvoke方法无疑是最方便的办法 ,见:温故而知新:WinForm/Silverlight多线程编程中如何更新UI控件的值
但今天发现WPF中的BeginInvoke却无法自动将匿名方法/Lambda表达式转变成Delegate类型(注:对委托,匿名方法,Lambda感到陌生的朋友先阅读温故而知新:Delegate,Action,Func,匿名方法,匿名委托,事件)
silverlight中的代码片段:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
private
void
button1_Click(
object
sender, RoutedEventArgs e)
{
Thread t =
new
Thread(TestMethod);
t.Start();
Thread t2 =
new
Thread(TestMethod2);
t2.Start(
"Hello World"
);
}
void
TestMethod() {
this
.Dispatcher.BeginInvoke(() => {
this
.textBlock1.Text = DateTime.Now.ToString(
"HH:mm:ss"
); });
}
void
TestMethod2(
object
s)
{
this
.Dispatcher.BeginInvoke(() => {
this
.textBlock1.Text =s.ToString() ; });
}
|
WPF中如果这样用,会报如下错误:
Cannot convert lambda expression to type 'System.Delegate' because it is not a delegate type
即:无法将lambda表达式转换为"System.Delegate",因为它不是delegate 类型
即使把Lambda表达式改成匿名方法的写法也不行:
1
2
3
4
|
public
void
TestMethod()
{
this
.Dispatcher.BeginInvoke(
delegate
() {
this
.textBlock1.Text = DateTime.Now.ToString(
"HH:mm:ss fff"
); });
}
|
仍然会报错:
Cannot convert anonymous method to type 'System.Delegate' because it is not a delegate type
即:无法将匿名方法转换为"System.Delegate",因为它不是delegate 类型
当然也可以自己定义一个Delegate类型用最传统的方法来写:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
delegate
void
MyDelegate();
delegate
void
MyDelegate2(
object
s);
public
void
TestMethod()
{
MyDelegate d =
new
MyDelegate(UpdateText);
this
.Dispatcher.BeginInvoke(d);
}
void
UpdateText()
{
this
.textBlock1.Text = DateTime.Now.ToString(
"HH:mm:ss fff"
);
}
void
UpdateText2(
object
s)
{
this
.textBlock1.Text = s.ToString();
}
public
void
TestMethod2(
object
s)
{
MyDelegate2 d =
new
MyDelegate2(UpdateText2);
this
.Dispatcher.BeginInvoke(d,
"Hello World"
);
}
|
但是这种写法太繁琐了,还得单独把方法的定义提取出来,同时还要定义相应的委托类型,难道不能象Silverlght中那样清爽一点么?
既然出错的原因就是编译器不自动做类型转换,那我们就来强制转换吧
1
2
3
4
5
6
7
8
9
|
public
void
TestMethod()
{
this
.Dispatcher.BeginInvoke((Action)
delegate
() {
this
.textBlock1.Text = DateTime.Now.ToString(
"HH:mm:ss fff"
); });
}
public
void
TestMethod2(
object
s)
{
this
.Dispatcher.BeginInvoke((Action)(() => {
this
.textBlock1.Text = s.ToString(); }));
}
|
这样就可以了,把匿名方法/Lambda表达式强制转换为Action,而Action实质就是委托类型,so,问题解决了!
不过仍然有点疑问:为啥编译器能自动认别Silverlight,却不认WPF呢?这算不算是编译器的BUG(或是需要改进的地方)
出处: http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。