• Wpf中Dispatcher.Invoke和Dispatcher.BeginInvoke的区别


    看下面的代码:

    new Thread(()=> {
    Application.Current.Dispatcher.BeginInvoke(new Action(() => {
    while (true)
    {
    Thread.Sleep(1000);
    }
    }), null);
    Console.WriteLine("test");
    
    }).Start();

    这段代码,会在控制台打印test,然后界面会一直卡住。界面卡住,说明while循环是在ui线程执行的,能够打印test,说明在执行Application.Current.Dispatcher.BeginInvoke时并没有阻塞当前界面,如果把BeginInvoke改成Invoke,那么test将不会被打印,说明Invoke方法的逻辑是把委托交给ui线程执行,并阻塞当前线程,直到委托结束。而BeginInvoke方法则首先新开一个线程,那新开的线程,再将委托交给ui线程处理。注意,最终执行委托的线程都是ui线程。所以,BeginInvoke由于有个新开线程的过程,不会阻塞当前线程。但仍然会阻塞界面。

    另外BeginInvoke是可以指定优先级的,通过方法BeginInvoke(DispatcherPriority, Delegate)来设置优先级。
    //------------------------------------------------------------------------------------------------------------------

    UI卡顿假死问题  转载于:https://www.cnblogs.com/YYkun/p/10782653.html

    误区1:使用不同的线程操作UI控件和耗时操作(即,跨线程操作UI控件CheckForIllegalCrossThreadCalls = false;),

    注意:此处只是为了记录......

    原始同步操作如下所示:

    private void button1_Click(object sender, EventArgs e)
            {
                Waintting waitting = new Waintting();
                waitting.Show();
                Thread.Sleep(5000);//模拟等待
                MessageBox.Show("连接数据库成功", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
                waitting.BeginInvoke((Action)waitting.Close);//BeginInvoke方法返回UI线程更新UI界面控件的机制。  
            }
    

      

    private void btnWatting_Click(object sender, EventArgs e)
            {
                Waintting waitting = new Waintting();
                waitting.Show();
                Task.Factory.StartNew(() => // 将阻塞线程的操作在另外一个线程中执行,这样就不会堵塞UI线程。  
                {
                    Thread.Sleep(5000);//模拟等待
                    MessageBox.Show("连接数据库成功", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    waitting.BeginInvoke((Action)waitting.Close);//BeginInvoke方法返回UI线程更新UI界面控件的机制。  
                });
     
            }
    

      

    调整后异步方式如下所示:

    private void WattingTest2_Click(object sender, EventArgs e)
           {
               Func<string> wait = () =>
               {
                   Thread.Sleep(5000);//模拟耗时操作,例如数据库操作等
                   return "abc";
               };
               wait.BeginInvoke(new AsyncCallback(result =>
               {
                   string rst = wait.EndInvoke(result);
                   this.Invoke((Action)(() => this.textBox1.AppendText(rst)));
               }), null);
           }
    

      

    // 盲区--------------------------------------------------  

     this.progressBar1.Dispatcher.BeginInvoke((ThreadStart)delegate { this.progressBar1.Value = 10); });
    
    
    
    Dispatcher.BeginInvoke(new Action(delegate { this.progressBar1.Value = 10);  }));
    
    
    
    Dispatcher.Invoke((Action)(() =>
    this.progressBar1.Value = 10);
    ));
    

      

  • 相关阅读:
    NET中的类型和装箱/拆箱原理
    转 C# 装箱和拆箱[整理]
    理解线程同步
    IsBackground的理解
    赛马会面试题
    FTP上传类
    FTPS加密上传
    转载WPF SDK研究 之 AppModel
    SQL Server查看错误日志存档编号及其详情
    Hive基础编程入门(一)
  • 原文地址:https://www.cnblogs.com/xfweb/p/15975365.html
Copyright © 2020-2023  润新知