廢話不多說,直接上代碼
public partial class Form1 : Form { private delegate void DelegateTest(); public Form1() { InitializeComponent(); } private void TripleKill() { MessageBox.Show("hello456"); this.Invoke(new DelegateTest(changeText1)); this.BeginInvoke(new DelegateTest(changeText)); this.BeginInvoke(new DelegateTest(DoubleKill)).ToString();//此事例證明了只有主線程才能去更改頁面,子線程想更改只能通過委托異步調用主線程然后整體性的告訴主線程自己都做了什么. } private void DoubleKill() { Thread.Sleep(3000); MessageBox.Show("456"); } private void button1_Click(object sender, EventArgs e) { Thread th = new Thread(new ThreadStart(TripleKill));
th.Start();
MessageBox.Show("789"); MessageBox.Show("hello world"); } private void changeText() { Thread.Sleep(4000); this.button1.Text = "click me"; } private void changeText1() { MessageBox.Show("hello123"); } }
首先需要明確的一點是子線程是無法改變頁面的,只有通過調用主線程(UI線程)才能改變,所以invoke和beginInvoke的區別在這時就顯現了出來,在用戶點擊button以后,新線程th調用TripleKill方法,在這個方法中hello world456 會顯示,這時子線程會阻塞(注意不是主線程哦),所以子線程不會繼續往下執行,反觀在主線程中,“789”顯示出來(當點擊確定后hello world也會顯示)當用戶點擊確定以后才能繼續執行下面的命令。然而在hello world456窗口點擊確定后,你會發現之前的hello world窗口無法操作了,因為在tripleKill方法中,th線程調用了主線程來更改頁面,hello world本來也是屬於主線程的,所以他沒辦法操作。然后關於invoke和begininvoke,我覺得主要是針對子線程來的,子線程調用的方法中如果是invoke,那么必須等主線程完成這個操作才能繼續往下執行,如果是beginInvoke,那么就會異步執行其中的方法,然后在反饋給主線程(反饋要注意哦),但是關於這個反饋,您會發現是所有的子線程執行完以后一起反饋,這個程序中的表現就是button的text的更改跟“456”的彈窗是一起出現的,並不是先彈窗,后更改,所以這一點證明了上述關於一起反饋的說法.