C#Delegate.Invoke、Delegate.BeginInvoke And Control.Invoke、Control.BeginInvoke
2014-04-23 17:55
260 查看
作者:EasonLeung
一、Delegate的Invoke、BeginInvoke
1、Delegate.Invoke (委托同步调用)
a、委托的Invoke方法,在当前线程中执行委托。
b、委托执行时阻塞当前线程,知道委托执行完毕,当前线程才继续向下执行。
c、委托的Invoke方法,类似方法的常规调用。
2、Delegate.BeginInvoke (委托异步调用)
a、委托的BeginInvoke方法,在线程池分配的子线程中执行委托
b、委托执行时不会阻塞主线程(调用委托的BeginInvoke线程),主线程继续向下执行。
c、委托执行时会阻塞子线程。
d、委托结束时,如果有返回值,子线程讲返回值传递给主线程;如果有回调函数,子线程将继续执行回调函数。
3、Demo
a、Delegate
b、Delegate.Invoke
c、Delegate.BeginInvoke
作者:EasonLeung
二、Control的Invoke、BeginInvoke
1、Control.Invoke (同步调用)
(1)在主线程(UI线程)中调用Control.Invoke
a、在主线程(UI线程)中调用Control.Invoke,先执行Invoke的方法,再执行Invoke后面的代码。
(2)在子线程中调用Control.Invoke
a、子线程中调用Control.Invoke,子线程将调用的方法封装成消息,调用API的RegisterWindowMessage()向UI窗口发送消息。 主线程继续向下执行,子线程处于阻塞状态。
b、当该消息被主线程执行完成后,子线程才能继续往下执行。
2、Delegate.BeginInvoke (异步调用)
(1)在主线程(UI线程)中调用Control.[b]BeginInvoke[/b]
a、在主线程(UI线程)中调用Control.BeginInvoke,将调用的方法封装成消息,调用API的RegisterWindowMessage()向UI窗口发送消息。先执行Invoke后面的代码,再执行Invoke的方法。
(2)在子线程中调用Control.[b]BeginInvoke[/b]
a、子线程中调用Control.BeginInvoke,子线程将调用的方法封装成消息,调用API的RegisterWindowMessage()向UI窗口发送消息。主线程继续向下执行,子线程也继续向下执行。
b、最后由主线程执行Invoke的方法。
3、Demo
a、在主线程(UI线程)中调用Control.Invoke
b、在子线程中调用Control.Invoke
c、在主线程(UI线程)中调用Control.BeginInvoke
c、在子线程中调用Control.BeginInvoke
代码下载
一、Delegate的Invoke、BeginInvoke
1、Delegate.Invoke (委托同步调用)
a、委托的Invoke方法,在当前线程中执行委托。
b、委托执行时阻塞当前线程,知道委托执行完毕,当前线程才继续向下执行。
c、委托的Invoke方法,类似方法的常规调用。
2、Delegate.BeginInvoke (委托异步调用)
a、委托的BeginInvoke方法,在线程池分配的子线程中执行委托
b、委托执行时不会阻塞主线程(调用委托的BeginInvoke线程),主线程继续向下执行。
c、委托执行时会阻塞子线程。
d、委托结束时,如果有返回值,子线程讲返回值传递给主线程;如果有回调函数,子线程将继续执行回调函数。
3、Demo
a、Delegate
private void btn_General_Click(object sender, EventArgs e) { txt_Message.Text = ""; txt_Message.Text += "主线程:"+ Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n"; //委托方法,在调用委托的线程中执行,本例中就是主线程(UI线程)。 //执行一些耗时的操作,就会阻塞主线程(UI线程) //委托的普通调用就等于方法的直接调用,del();等价于SomeWork(); del(); //SomeWork(); txt_Message.Text += "\r\n主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n"; }
b、Delegate.Invoke
private void btn_Main_Invoke_Click(object sender, EventArgs e) { txt_Message.Text = ""; txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n"; //委托的同步调用,其实就是等价于委托的普通调用。 del.Invoke(); txt_Message.Text += "\r\n主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n"; }
private void btn_Sub_Invoke_Click(object sender, EventArgs e) { txt_Message.Text = ""; txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n"; //开启新的线程执行委托,主线程(UI线程)继续向下执行 new Thread(() => { txt_Message.Text += "\r\n----子线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n"; //委托在调用线程中执行,并阻塞调用线程,知道委托方法执行结束。 del.Invoke(); txt_Message.Text += "\r\n----子线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n"; }).Start(); txt_Message.Text += "\r\n主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n"; }
c、Delegate.BeginInvoke
private void btn_Main_BeginInvoke_Click(object sender, EventArgs e) { txt_Message.Text = ""; txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n"; //委托异步调用 //1、委托方法,在线程池中分配的子线程中执行。 //2、主线程和子线程同时执行。 //3、子线程结束之后,如果有返回值得话,将返回值传递给主线程。如果有回调函数的话,继续在子线程中执行回调函数。 //有异常,控件不能在子线程中访问修改。 //避免这类异常有两种方法 //1、手动关闭控件的跨线程安全检查Control.CheckForIllegalCrossThreadCalls = false;(不建议使用) //2、使用控件的Invoke方法。(推荐使用) del.BeginInvoke(null,null); txt_Message.Text += "\r\n主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n"; }
private void btn_Sub_BeginInvoke_Click(object sender, EventArgs e) { txt_Message.Text = ""; txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n"; //开启新的线程执行委托,主线程(UI线程)继续向下执行 new Thread(() => { txt_Message.Text += "\r\n----子线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n"; //在线程池中分配的子线程中执行委托方法,调用委托的线程继续向下执行。 del.BeginInvoke(null, null); txt_Message.Text += "\r\n----子线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n"; }).Start(); txt_Message.Text += "\r\n主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n"; }
作者:EasonLeung
二、Control的Invoke、BeginInvoke
1、Control.Invoke (同步调用)
(1)在主线程(UI线程)中调用Control.Invoke
a、在主线程(UI线程)中调用Control.Invoke,先执行Invoke的方法,再执行Invoke后面的代码。
(2)在子线程中调用Control.Invoke
a、子线程中调用Control.Invoke,子线程将调用的方法封装成消息,调用API的RegisterWindowMessage()向UI窗口发送消息。 主线程继续向下执行,子线程处于阻塞状态。
b、当该消息被主线程执行完成后,子线程才能继续往下执行。
2、Delegate.BeginInvoke (异步调用)
(1)在主线程(UI线程)中调用Control.[b]BeginInvoke[/b]
a、在主线程(UI线程)中调用Control.BeginInvoke,将调用的方法封装成消息,调用API的RegisterWindowMessage()向UI窗口发送消息。先执行Invoke后面的代码,再执行Invoke的方法。
(2)在子线程中调用Control.[b]BeginInvoke[/b]
a、子线程中调用Control.BeginInvoke,子线程将调用的方法封装成消息,调用API的RegisterWindowMessage()向UI窗口发送消息。主线程继续向下执行,子线程也继续向下执行。
b、最后由主线程执行Invoke的方法。
3、Demo
a、在主线程(UI线程)中调用Control.Invoke
private void btn_Main_Invoke_Click(object sender, EventArgs e) { //执行顺序:代码A -> 代码Invoke -> 代码B //都是在主线程中执行 txt_Message.Text = ""; txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n"; //代码A this.txt_Message.Invoke(del); //代码B txt_Message.Text += "\r\n主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n"; }
b、在子线程中调用Control.Invoke
private void btn_Sub_Invoke_Click(object sender, EventArgs e) { //执行顺序: //1、代码A(主线程执行) //2、代码D(主线程执行) 和 代码B(子线程执行) 并发执行 //3、封装消息,并在UI线程中注册消息(子线程执行) //4、代码Invoke(主线程执行) //5、代码C(子线程执行) txt_Message.Text = ""; txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n"; //代码A new Thread(() => { //代码B int temp = 0; this.txt_Message.Invoke(del); //代码C temp = 1; }).Start(); //代码D txt_Message.Text += "\r\n主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n"; }
c、在主线程(UI线程)中调用Control.BeginInvoke
private void btn_Main_BeginInvoke_Click(object sender, EventArgs e) { //执行顺序:代码A -> 封装消息,并在UI线程中注册消息 -> 代码B -> 代码Invoke //都是在主线程中执行 txt_Message.Text = ""; txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n"; //代码A this.txt_Message.BeginInvoke(del); //代码B txt_Message.Text += "\r\n主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n"; }
c、在子线程中调用Control.BeginInvoke
private void btn_Sub_BeginInvoke_Click(object sender, EventArgs e) { //执行顺序: //1、代码A(主线程执行) //2、代码D(主线程执行) 和 代码B(子线程执行) 并发执行 //3、封装消息,并在UI线程中注册消息(子线程执行) //4、代码C(子线程执行) //5、代码Invoke(主线程执行) txt_Message.Text = ""; txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n"; //代码A new Thread(() => { //代码B int temp = 0; this.txt_Message.BeginInvoke(del); //代码C temp = 1; }).Start(); //代码D txt_Message.Text += "\r\n主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n"; }
代码下载