夜的第七章

WEB开发个人博客。

« 起床了,头还有些疼.....[转]在.NET客户端程序中使用多线程 »

看一下不同线程对同一窗体的调用 --以前用到到没搞懂的问题

以前只是用到,但真没懂。
今天有时间了,查查资料。看一下运行的机制。不清楚在.NET 1.1下面是怎样的了,好象在那个平台下没用过?要不就没这个问题。

在VS2005下,两个线程对一个窗体(或一个控件更恰当)进行操作时,会出现错误。

查阅MSDN资料,看到以下一段话:

Windows 窗体中的控件被绑定到特定的线程,不具备线程安全性。因此,如果从另一个线程调用控件的方法,那么必须使用控件的一个 Invoke 方法来将调用封送到适当的线程。

如果尚未创建控件的句柄,您就不能简单地在控件上调用属性、方法或事件。这可能导致在后台线程上创建控件的句柄,从而隔离不带消息泵的线程上的控件并使应用程序不稳定。

一种解决方案是等到已经创建了窗体的句柄,然后启动后台线程。通过调用 Handle 属性强制创建句柄,或者等待 Load 事件启动后台进程。

一种更好的解决方案是使用 SynchronizationContext 返回的 SynchronizationContext,而不是使用控件进行线程间封送处理。

第一种方案即是把要实现的函数封装一下,传给控件的Invoke,使其内部调用。

代码:


第二种方案把控件的上下文传入线程,利用线程来发送。

//注:以下代码段摘自http://blog.joycode.com/saucer/archive/2007/05/11/102383.aspx




这样我们可以看到第二种方案是MS把线程的同步异步给封装了一个类SynchronizationContext ,这个类的Invoke方法接受调用用到的参数,并放到线程池的执行队列中等待执行。至于说第二种方案是更好的解决方案,难道是因为第二种方案比第一种方案代码更安全?上面一段话中提到第一种方案可能导致在后台线程上创建控件的句柄,从而隔离不带消息泵的线程上的控件并使应用程序不稳定。在网上找到这么一段话:
------------------------------------------------------------------------------------------
Windows Forms类库建立在大家所熟知的User32 Win32 API 基础上。User32实现了GUI的基本元素,例如窗体,菜单及按钮之类等。所有由User32实现的窗体和控件都使用了事件驱动型结构。

   这里简单的讲讲它们如何工作。发生在窗体上的事情,例如鼠标单击,坐标变化,大小变化和重绘请求,都称作事件。在User32 API模型中的事件是由窗体消息表示的。每一个窗体有一个函数,叫做窗口过程或WndProc,它由应用程序实现。WndProc为窗体负责处理窗体消息。

   但是WndProc不是神奇的被系统调用。相反,应用程序必须调用GetMessage主动地从系统中得到窗体消息。该消息被应用程序调用DispatchMethod API方法分配到它们的目标窗体的WndProc方法中。应用程序只是简单的循环接收和分配窗口消息,一般叫做消息泵或消息循环。线程拥有所有窗体,这样它就可以提取消息,WndProc函数也被同样的线程所调用。
------------------------------------------------------------------------------------------


还没搞懂。。。继续研究。。。。。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。



[2007 - 2011] © Leadnt.com