zoukankan      html  css  js  c++  java
  • C#Delegate.Invoke、Delegate.BeginInvoke And Control.Invoke、Control.BeginInvoke

    作者: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

     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         }



    作者: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.BeginInvoke

        a、在主线程(UI线程)中调用Control.BeginInvoke,将调用的方法封装成消息,调用API的RegisterWindowMessage()向UI窗口发送消息。先执行Invoke后面的代码,再执行Invoke的方法。

      (2)在子线程中调用Control.BeginInvoke

        a、子线程中调用Control.BeginInvoke,子线程将调用的方法封装成消息,调用API的RegisterWindowMessage()向UI窗口发送消息。主线程继续向下执行,子线程也继续向下执行。

        b、最后由主线程执行Invoke的方法

    3、Demo

      a、在主线程(UI线程)中调用Control.Invoke

     1         private void btn_Main_Invoke_Click(object sender, EventArgs e)
     2         {
     3             //执行顺序:代码A -> 代码Invoke -> 代码B
     4             //都是在主线程中执行
     5 
     6             txt_Message.Text = "";
     7             txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作
    ";
     8             //代码A
     9             this.txt_Message.Invoke(del);
    10             //代码B
    11             txt_Message.Text += "
    主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束
    ";
    12         }

      b、在子线程中调用Control.Invoke

     1         private void btn_Sub_Invoke_Click(object sender, EventArgs e)
     2         {
     3             //执行顺序:
     4             //1、代码A(主线程执行)
     5             //2、代码D(主线程执行) 和 代码B(子线程执行) 并发执行
     6             //3、封装消息,并在UI线程中注册消息(子线程执行)
     7             //4、代码Invoke(主线程执行)
     8             //5、代码C(子线程执行)
     9 
    10             txt_Message.Text = "";
    11             txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作
    ";
    12             //代码A
    13             new Thread(() =>
    14             {
    15                 //代码B
    16                 int temp = 0;
    17                 this.txt_Message.Invoke(del);
    18                 //代码C
    19                 temp = 1;
    20             }).Start();
    21             //代码D
    22             txt_Message.Text += "
    主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束
    ";
    23         }

      c、在主线程(UI线程)中调用Control.BeginInvoke

     1         private void btn_Main_BeginInvoke_Click(object sender, EventArgs e)
     2         {
     3             //执行顺序:代码A -> 封装消息,并在UI线程中注册消息 -> 代码B -> 代码Invoke
     4             //都是在主线程中执行
     5 
     6             txt_Message.Text = "";
     7             txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作
    ";
     8             //代码A
     9             this.txt_Message.BeginInvoke(del);
    10             //代码B
    11             txt_Message.Text += "
    主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束
    ";
    12         }

      c、在子线程中调用Control.BeginInvoke

     1         private void btn_Sub_BeginInvoke_Click(object sender, EventArgs e)
     2         {            
     3             //执行顺序:
     4             //1、代码A(主线程执行)
     5             //2、代码D(主线程执行) 和 代码B(子线程执行) 并发执行
     6             //3、封装消息,并在UI线程中注册消息(子线程执行)
     7             //4、代码C(子线程执行)
     8             //5、代码Invoke(主线程执行)
     9 
    10             txt_Message.Text = "";
    11             txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作
    ";
    12             //代码A
    13             new Thread(() =>
    14             {
    15                 //代码B
    16                 int temp = 0;
    17                 this.txt_Message.BeginInvoke(del);
    18                 //代码C
    19                 temp = 1;
    20             }).Start();
    21             //代码D
    22             txt_Message.Text += "
    主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束
    ";
    23         }

    代码下载

  • 相关阅读:
    如何测得存储空间大小
    打印阿斯科码 和 打印字符
    正常血压
    c语言知识(1)
    子组件和父组件
    RESTful风格API
    django APIview使用
    django 基础
    npm install异常error code EPERM
    springsecurity 多httpsecurity配置
  • 原文地址:https://www.cnblogs.com/EasonLeung/p/3683492.html
Copyright © 2011-2022 走看看