zoukankan      html  css  js  c++  java
  • 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(或是需要改进的地方)

    作者:菩提树下的杨过
    出处:http://yjmyzz.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    思考未来:你的目标是什么
    从非同凡响开始:绝不要做他人也在做的事
    Elasticsearch的内置分词器
    Elasticsearch倒排索引的核心组成
    Session 与 JWT
    vue全屏组件
    css弹性盒骰子
    es6模块化
    移动端适配
    echarts-3D地图
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/1689256.html
Copyright © 2011-2022 走看看