欢迎来到天天文库
浏览记录
ID:6493895
大小:165.50 KB
页数:8页
时间:2018-01-15
《c#窗体中invoke和begininvoke方法详解》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库。
1、在Invoke或者BeginInvoke的使用中无一例外地使用了委托Delegate,至于委托的本质请参考我的另一随笔:对.net事件的看法。 一、为什么Control类提供了Invoke和BeginInvoke机制?关于这个问题的最主要的原因已经是dotnet程序员众所周知的,我在此费点笔墨再次记录到自己的日志,以便日后提醒一下自己。1、windows程序消息机制WindowsGUI程序是基于消息机制的,有个主线程维护着一个消息泵。这个消息泵让windows程序生生不息。 WindowsGUI程序
2、的消息循环 Windows程序有个消息队列,窗体上的所有消息是这个队列里面消息的最主要来源。这里的while循环使用了GetMessage()这个方法,这是个阻塞方法,也就是队列为空时方法就会被阻塞,从而这个while循环停止运动,这避免了一个程序把cpu无缘无故地耗尽,让其它程序难以得到响应。当然在某些需要cpu最大限度运动的程序里面就可以使用另外的方法,例如某些3d游戏或者及时战略游戏中,一般会使用PeekMessage()这个方法,它不会被windows阻塞,从而保证整个游戏的流畅和比较高的帧速。这个主线程维护着整个窗体以及上面的子控件。当它得到一个消息,就会调用DispatchMes
3、sage方法派遣消息,这会引起对窗体上的窗口过程的调用。窗口过程里面当然是程序员提供的窗体数据更新代码和其它代码。2、dotnet里面的消息循环publicstaticvoidMain(string[]args){ Formf=newForm(); Application.Run(f);}Dotnet窗体程序封装了上述的while循环,这个循环就是通过Application.Run方法启动的。3、线程外操作GUI控件的问题如果从另外一个线程操作windows窗体上的控件,就会和主线程产生竞争,造成不可预料的结果,甚至死锁。因此windowsGUI编程有一个规则,就是只能通过创建控件的线程来
4、操作控件的数据,否则就可能产生不可预料的结果。因此,dotnet里面,为了方便地解决这些问题,Control类实现了ISynchronizeInvoke接口,提供了Invoke和BeginInvoke方法来提供让其它线程更新GUI界面控件的机制。publicinterfaceISynchronizeInvoke{ [HostProtection(SecurityAction.LinkDemand,Synchronization=true,ExternalThreading=true)] IAsyncResultBeginInvoke(Delegatemethod,obj
5、ect[]args); objectEndInvoke(IAsyncResultresult); objectInvoke(Delegatemethod,object[]args); boolInvokeRequired{get;}}}如果从线程外操作windows窗体控件,那么就需要使用Invoke或者BeginInvoke方法,通过一个委托把调用封送到控件所属的线程上执行。二、消息机制---线程间和进程间通信机制1、window消息发送Windows消息机制是windows平台上的线程或者进程间通信机制之一。Windows消息值其实就是定义的一个数据结构
6、,最重要的是消息的类型,它就是一个整数;然后就是消息的参数。消息的参数可以表示很多东西。Windows提供了一些api用来向一个线程的消息队列发送消息。因此,一个线程可以向另一个线程的消息队列发送消息从而告诉对方做什么,这样就完成了线程间的通信。有些api发送消息需要一个窗口句柄,这种函数可以把消息发送到指定窗口的主线程消息队列;而有些则可以直接通过线程句柄,把消息发送到该线程消息队列中。 用消息机制通信 SendMessage是windowsapi,用来把一个消息发送到一个窗口的消息队列。这
7、个方法是个阻塞方法,也就是操作系统会确保消息的确发送到目的消息队列,并且该消息被处理完毕以后,该函数才返回。返回之前,调用者将会被暂时阻塞。PostMessage也是一个用来发送消息到窗口消息队列的api函数,但这个方法是非阻塞的。也就是它会马上返回,而不管消息是否真的发送到目的地,也就是调用者不会被阻塞。2、InvokeandBeginInvoke
此文档下载收益归作者所有