Silverlight与WPF中BeginInvoke的差异

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

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

silverlight中的代码片段:

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

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

        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中那样清爽一点么?

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

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(或是需要改进的地方)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏技术博客

Dynamic 动态类型 和双问号??的使用

1.dynamic关键字用于声明一个动态对象,然后通过该动态对象去调用方法或读写属性。以前我们都是在运行时通过反射,Emit,CodeDom等技术来完成。创建一...

2152
来自专栏林德熙的博客

win10 uwp unix timestamp 时间戳 转 DateTime

有时候需要把网络的 unix timestamp 转为 C# 的 DateTime ,在 UWP 可以如何转换?

701
来自专栏二进制文集

JSON Java 解析

要使程序可以运行必须引入JSON-lib包——org.json.jar包。综合来看,这个JAR包比较好用。

1632
来自专栏landv

从零开始学习C#——HelloWorld(一)

1445
来自专栏菩提树下的杨过

java学习:调用 java web service

先写一个java的class:AwbModel(相当于要在web service中传输的实体对象) package webservicesample; pub...

2706
来自专栏GreenLeaves

C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

4022
来自专栏hbbliyong

C#基础知识回顾-- 反射(3)

获取Type对象的构造函数: 前一篇因为篇幅问题因为篇幅太短被移除首页,反射这一块还有一篇“怎样在程序集中使用反射”, 其他没有什么可以写的了,前两篇主要是铺...

2976
来自专栏飞扬的花生

集合中随机取不重复的索引

有时候希望从一个集合中随机取n个元素不重复 那么就取到这n个数字的索引 public static int[] GetRandomArray(int Numb...

3298
来自专栏码农阿宇

关于C#委托的一些学习笔记

1.什么是委托就是把方法作为参数传给另一个方法。委托说指向的函数,必须和函数具有相同的签名(返回值和参数类型) Public delegate void D...

2757
来自专栏技术博客

一步一步学Linq to sql(一):预备知识

  Linq to sql(或者叫DLINQ)是LINQ(.NET语言集成查询)的一部分,全称基于关系数据的 .NET 语言集成查询,用于以对象形式管理关系数据...

951

扫码关注云+社区

领取腾讯云代金券