zoukankan      html  css  js  c++  java
  • Invoke和BeginInvoke

    参考:Invoke和BeginInvoke理解

    Windows GUI程序基于消息循环机制

    public static void Main(string[] args)

    {

       Form f = new Form();

       Application.Run(f);

    }

    .NET窗体程序封装了上述的while循环,这个循环就是通过Application.Run方法启动的。如果从别的线程上操作窗体上的控件,就会和主线程产生竞争,造成不可预料的结果,甚至死锁。因此windows GUI编程有一个规则,就是只能通过创建控件的线程来操作控件的数据

    在.NET中,Control类实现了ISynchronizeInvoke接口,提供了Invoke和BeginInvoke方法来提供让其它线程更新GUI界面控件的机制,通过一个委托将调用封送到控件所在的线程上执行。

    Invoke或者BeginInvoke方法都需要一个委托对象作为参数。委托类似于回调函数的地址,因此调用者通过这两个方法就可以把需要调用的函数地址封送给界面线程。这些方法里面如果包含了更改控件状态的代码,那么由于最终执行这个方法的是界面线程,从而避免了竞争条件,避免了不可预料的问题。如果其它线程直接操作界面线程所属的控件,那么将会产生竞争条件,造成不可预料的结果。

    使用Invoke完成一个委托方法的封送,是一个同步方法。也就是说在Invoke封送的方法被执行完毕前,Invoke方法不会返回,从而调用者线程将被阻塞。

    使用BeginInvoke方法封送一个委托方法,是一个异步方法。也就是该方法封送完毕后马上返回,不会等待委托方法的执行结束,调用者线程将不会被阻塞。但是调用者也可以使用EndInvoke方法或者其它类似WaitHandle机制等待异步操作的完成。但是在内部实现上,Invoke和BeginInvoke都是用了PostMessage方法,从而避免了SendMessage带来的问题。而Invoke方法的同步阻塞是靠WaitHandle机制来完成的。

    InvokeRequired属性用来在编程的时候确定一个对象访问UI控件的时候是否需要使用Invoke或者BeginInvoke来进行封送。如果不需要那么就可以直接更新。在调用者对象和UI对象同属一个线程的时候这个属性返回false。

      private void button1_Click(object sender, EventArgs e)
            {
                if(this.button1.InvokeRequired)
                {
                    this.button1.BeginInvoke(new EventHandler(button1_Click), new object[] { sender, e });
                }
                else
                {
                    this.button1.Text = "Hello";
                }
            }
  • 相关阅读:
    《Android 4游戏高级编程(第2版)》书评
    push研究——Apache Mina探索初步
    Android UI开发第二十三篇——分享书架UI实现
    cookie学习总结
    Web.xml配置详解
    Java序列化的机制和原理
    Java高级技术(汇总中...)
    [Java]HashMap的两种排序方式
    jdk与jre的区别
    DM,NLP常用算法汇总
  • 原文地址:https://www.cnblogs.com/larry-xia/p/9812475.html
Copyright © 2011-2022 走看看