背景:在winform UI中,有時需要對控制項進行比較頻繁的刷新,如進度條、picturebox顯示視頻等。如果在主線程進行這些刷新操作,操作還未完成就將執行下一次刷新,程式將發生錯誤;如果只是創建另一個線程執行這些操作,將和主線程產生競爭,造成界面鎖死(因此windows GUI編程有一個規則,就
背景:在winform UI中,有時需要對控制項進行比較頻繁的刷新,如進度條、picturebox顯示視頻等。如果在主線程進行這些刷新操作,操作還未完成就將執行下一次刷新,程式將發生錯誤;如果只是創建另一個線程執行這些操作,將和主線程產生競爭,造成界面鎖死(因此windows GUI編程有一個規則,就是只能通過創建控制項的線程來操作控制項的數據,否則就可能產生不可預料的結果)。這時候,我們就可以用委托與非同步來解決這個問題。
委托:回顧一下委托 ,一、定義委托,委托定義的參數與傳遞給委托的方法的參數一致。二、聲明與實例化。三、調用,將委托作為參數供方法調用。
非同步:Windows窗體控制項,唯一可以從創建它的線程之外的線程中調用的是Invoke()、BeginInvoke()、EndInvoke()方法和InvokeRequired屬性。這些方法會切換到創建控制項的線程上,以調用賦予一個委托參數的方法,該委托參數可以傳遞給這些方法。
關於Invoke()與BeginInvoke():其中BeginInvoke()、EndInvoke()方法是Invoke()方法的非同步版本。相同點:都需要一個委托對象作為參數。不同點:Invoke()是同步方法,Invoke封送的方法被執行完畢前,Invoke()不會返回,從而調用者線程將被阻塞;需要等待UI操作執行完畢後繼續執行線程時考慮使用。而BeginInvoke()相反,是非同步方法,方法調後立即返回,不用等待委托方法的執行結束,主線程就不會阻塞。
Delegate.BeginInvoke方法從ThreadPool取出一個線程來執行這個方法,以獲得非同步執行效果。Control.BeginInvoke方法並不會另開線程。
參考:http://blog.csdn.net/stxyc/article/details/16945581
初學C#,理解的不是很透徹,一步一步來,循序漸進。
下麵是一個進度條的小程式:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace progressBar { public partial class Form1 : Form { delegate void ShowProgressDelegate(); delegate void RunTaskDelegate(); public Form1() { InitializeComponent(); this.progressBar1.Maximum = 50; this.progressBar1.Step = 1; } private void startBtn_Click(object sender, EventArgs e) { RunTaskDelegate runTask = new RunTaskDelegate(RunTask); // 委托非同步調用方法 runTask.BeginInvoke(null, null); } private void closeBtn_Click(object sender, EventArgs e) { this.Close(); } //進度條增加 void ShowProgress() { this.progressBar1.PerformStep(); } //模擬工作方法 public void RunTask() { ShowProgressDelegate showProgress = new ShowProgressDelegate(ShowProgress); int iTotal = 50;//工作量 for (int i = 0; i < iTotal; i++) { System.Threading.Thread.Sleep(1000);//模擬工作 this.BeginInvoke(showProgress); } } } }
我目前的理解是:RunTaskDelegate的作用是從另一個線程調用RunTask()方法(此方法中包含主線程的休眠),可以避免休眠期間界面無響應。ShowProgressDelegate的作用就是非同步調用ShowProgress()方法,從而避免非UI線程操作控制項產生的異常。