废话不多说,直接上代码
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”的弹窗是一起出现的,并不是先弹窗,后更改,所以这一点证明了上述关于一起反馈的说法.