微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Silverlight与WPF中BeginInvoke的差异



Silverlight/WPF中,如果要在多线程中对界面控件值做修改,用dispatcher对象的BeginInvoke方法无疑是最方便的办法 ,见:温故而知新:WinForm/Silverlight多线程编程中如何更新UI控件的值

但今天发现WPF中的BeginInvoke却无法自动将匿名方法/Lambda表达式转变成Delegate类型(注:对委托,匿名方法,Lambda感到陌生的朋友先阅读温故而知新:Delegate,Action,Func,匿名方法,匿名委托,事件)

silverlight中的代码片段:



privatevoid button1_Click(objectsender,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表达式改成匿名方法的写法也不行:

?
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类型用最传统的方法来写:

?
delegatevoid MyDelegate();

delegatevoid MyDelegate2(objects);

 

 

 

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();

}

 

publicvoid TestMethod2(objects)

{

    MyDelegate2 d =new MyDelegate2(UpdateText2);

    this.dispatcher.BeginInvoke(d,"Hello World");

}


但是这种写法太繁琐了,还得单独把方法的定义提取出来,同时还要定义相应的委托类型,难道不能象Silverlght中那样清爽一点么?

既然出错的原因就是编译器不自动做类型转换,那我们就来强制转换吧

?
public void TestMethod()

{

    this.dispatcher.BeginInvoke((Action)delegate() { this.textBlock1.Text = DateTime.Now.ToString("HH:mm:ss fff"); });

}        

 

public void TestMethod2(objects)

{

    this.dispatcher.BeginInvoke((Action)(() => {this.textBlock1.Text = s.ToString(); }));

}


 

这样就可以了,把匿名方法/Lambda表达式强制转换为Action,而Action实质就是委托类型,so,问题解决了!


不过仍然有点疑问:为啥编译器能自动认别Silverlight,却不认WPF呢?这算不算是编译器的BUG(或是需要改进的地方)

作者: 菩提树下的杨过
出处: http://yjmyzz.cnblogs.com 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐