1. 程式人生 > 其它 >Wpf中Dispatcher.Invoke和Dispatcher.BeginInvoke的區別

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