zoukankan      html  css  js  c++  java
  • 我理解的invoke和begininvoke

    一直对invoke和begininvoke的使用和概念比较混乱,这两天看了些资料,对这两个的用法和原理有了些新的认识和理解。

    首先说下,invoke和begininvoke的使用有两种情况:

      1. control中的invoke、begininvoke。

      2. delegrate中的invoke、begininvoke。  

      这两种情况是不同的,我们这里要讲的是第1种。下面我们在来说下.NET中对invoke和begininvoke的官方定义。

      control.invoke(参数delegate)方法:在拥有此控件的基础窗口句柄的线程上执行指定的委托。

      control.begininvoke(参数delegate)方法:在创建控件的基础句柄所在线程上异步执行指定委托。

      根据这两个概念我们大致理解invoke表是同步、begininvoke表示异步。但是如何来进行同步和异步呢?我们来做一个测试。

    invoke 例子:

    private void button1_Click(object sender, EventArgs e)
    {
                MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"AAA");
                invokeThread = new Thread(new ThreadStart(StartMethod));
                invokeThread.Start();
                string a = string.Empty;
                for (int i = 0; i < 3; i++)      //调整循环次数,看的会更清楚
                {
                    Thread.Sleep(1000);  
                    a = a + "B";
                }
                MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+a);
    }

    private void StartMethod()
    {
                MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"CCC");
                button1.Invoke(new invokeDelegate(invokeMethod)); 
                MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"DDD");
    }

    private void invokeMethod()
    {
                //Thread.Sleep(3000);
                MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString() + "EEE");

    结论:我们运行后,看下程序的运行顺序,1AAA->3CCC和1BBB->1EEE ->3DDD 。 

    解释:主线程运行1AAA,然后1BBB和子线程3CCC同时执行,然后通过invoke来将invokemethod方法提交给主线程,然后子线程等待主线程执行,直到主线程将invokemethod方法执行完成(期间必须等待主线程的任务执行完成,才会去执行invoke提交的任务),最后执行子线程3DDD。

    begininvoke 例子:

    private void button1_Click(object sender, EventArgs e)
    {
                MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"AAA");
                invokeThread = new Thread(new ThreadStart(StartMethod));
                invokeThread.Start();
                string a = string.Empty;
                for (int i = 0; i < 3; i++)      //调整循环次数,看的会更清楚
                {
                    Thread.Sleep(1000);  
                    a = a + "B";
                }
                MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+a);
    }

    private void StartMethod()
    {
                MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"CCC");
                button1.BeginInvoke(new invokeDelegate(invokeMethod)); 
                MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"DDD");
    }

    private void beginInvokeMethod()
            {
                //Thread.Sleep(3000);
                MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString() + "EEEEEEEEEEEE");
            }

    结论: 我们运行后看看执行的结果:1AAA->1BBB和3CCC->1EEE和3DDD。

    解释: 主线程运行1AAA,然后1BBB和子线程3CCC同时执行,然后通过begininvoke来将invokemethod方法提交给主线程,然后主线程执行1EEE(主线程自己的任务执行完成), 同时子线程继续执行3DDD。

    通过这个两段代码的测试比较,我们会发现其实invoke和begininvoke所提交的委托方法都是在主线程中执行的,其实根据我invoke和begininvoke的定义我们要在子线程中来看这个问题,在invoke例子中我们会发现invoke所提交的委托方法执行完成后,才能继续执行DDD;在begininvoke例子中我们会发现begininvoke所提交的委托方法后,子线程讲继续执行DDD,不需要等待委托方法的完成。 那么现在我们在回想下invoke(同步)和begininvoke(异步)的概念,其实它们所说的意思是相对于子线程而言的,其实对于控件的调用总是由主线程来执行的。我们很多人搞不清这个同步和异步,主要还是因为我们把参照物选错了。其实有时候光看概念是很容易理解错误的。

  • 相关阅读:
    Swift5.3 语言参考(八) 模式
    Swift5.3 语言参考(七) 属性
    Swift5.3 语言参考(六) 声明
    Swift5.3 语言参考(五) 语句
    Swift5.3 语言参考(四) 表达式
    Swift5.3 语言参考(三) 类型
    Swift5.3 语言参考(一) 关于语言参考
    有效率的会议方式
    有效率的会议方式
    高中生活--第5篇--学英语的故事(四大难题)
  • 原文地址:https://www.cnblogs.com/ajunForNet/p/4517762.html
Copyright © 2011-2022 走看看