Delegate的Invoke、BeginInvoke
1、Delegate.Invoke (委托同步调用)
a、委托的Invoke方法,在当前线程中执行委托。
b、委托执行时阻塞当前线程,知道委托执行完毕,当前线程才继续向下执行。
c、委托的Invoke方法,类似方法的常规调用。
2、Delegate.BeginInvoke (委托异步调用)
a、委托的BeginInvoke方法,在线程池分配的子线程中执行委托
b、委托执行时不会阻塞主线程(调用委托的BeginInvoke线程),主线程继续向下执行。
c、委托执行时会阻塞子线程。
d、委托结束时,如果有返回值,子线程讲返回值传递给主线程;如果有回调函数,子线程将继续执行回调函数。
3、Demo
a、Delegate
1 private void btn_General_Click(object sender, EventArgs e) 2 { 3 txt_Message.Text = ""; 4 txt_Message.Text += "主线程:"+ Thread.CurrentThread.ManagedThreadId + "---开始工作 "; 5 //委托方法,在调用委托的线程中执行,本例中就是主线程(UI线程)。 6 //执行一些耗时的操作,就会阻塞主线程(UI线程) 7 //委托的普通调用就等于方法的直接调用,del();等价于SomeWork(); 8 del(); 9 //SomeWork(); 10 txt_Message.Text += " 主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束 "; 11 }
b、Delegate.Invoke
1 private void btn_Main_Invoke_Click(object sender, EventArgs e) 2 { 3 txt_Message.Text = ""; 4 txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作 "; 5 //委托的同步调用,其实就是等价于委托的普通调用。 6 del.Invoke(); 7 txt_Message.Text += " 主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束 "; 8 }
1 private void btn_Sub_Invoke_Click(object sender, EventArgs e) 2 { 3 txt_Message.Text = ""; 4 txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作 "; 5 6 //开启新的线程执行委托,主线程(UI线程)继续向下执行 7 new Thread(() => { 8 txt_Message.Text += " ----子线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作 "; 9 //委托在调用线程中执行,并阻塞调用线程,知道委托方法执行结束。 10 del.Invoke(); 11 txt_Message.Text += " ----子线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束 "; 12 }).Start(); 13 14 txt_Message.Text += " 主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束 "; 15 }
c、Delegate.BeginInvoke
1 private void btn_Main_BeginInvoke_Click(object sender, EventArgs e) 2 { 3 txt_Message.Text = ""; 4 txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作 "; 5 //委托异步调用 6 //1、委托方法,在线程池中分配的子线程中执行。 7 //2、主线程和子线程同时执行。 8 //3、子线程结束之后,如果有返回值得话,将返回值传递给主线程。如果有回调函数的话,继续在子线程中执行回调函数。 9 10 //有异常,控件不能在子线程中访问修改。 11 //避免这类异常有两种方法 12 //1、手动关闭控件的跨线程安全检查Control.CheckForIllegalCrossThreadCalls = false;(不建议使用) 13 //2、使用控件的Invoke方法。(推荐使用) 14 del.BeginInvoke(null,null); 15 txt_Message.Text += " 主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束 "; 16 }
1 private void btn_Sub_BeginInvoke_Click(object sender, EventArgs e) 2 { 3 txt_Message.Text = ""; 4 txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作 "; 5 6 //开启新的线程执行委托,主线程(UI线程)继续向下执行 7 new Thread(() => 8 { 9 txt_Message.Text += " ----子线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作 "; 10 //在线程池中分配的子线程中执行委托方法,调用委托的线程继续向下执行。 11 del.BeginInvoke(null, null); 12 txt_Message.Text += " ----子线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束 "; 13 }).Start(); 14 15 txt_Message.Text += " 主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束 "; 16 }
文章转载自:https://www.cnblogs.com/EasonLeung/p/3683492.html