线程中怎么实时显示数据到界面-

线程中如何实时显示数据到界面----------------------------------
不谈论用发送消息的方法. 
mfc工程, 创建了一个线程,这线程负责实时显示一些数据到 界面上. CMainFrame 里保存了一些界面控件的指针. 自己是这样做的: 直接传递CMainFrame指针,过去后,成员的变量值是正确的, 但通过成员指针调用 界面相关的函数就会出错,  

 逛了下论坛,看到有一种是传递 hwnd给线程, 但我传CMainFrame.m_hwnd过去 CWnd::FromHandle((HWND)lpPar), 能获得个指针pMain, 但pMain指针里面的成员不是正确的值. 传递句柄的方法可行?

------解决方案--------------------
对于MFC界面来说。正确的做法就是发送消息给主线程。
------解决方案--------------------
线程中处理界面更新,有时候使程序崩溃.
比如说调用 UpdateData这类的函数,界面很容易崩溃的.
------解决方案--------------------
楼主的做法是可行的,是常用的方法,其他线程更新界面,其实更新界面时,也是用的发送消息。所以,造成UI更新崩溃的时候,通常是在停止线程得时候,主线程和线程之间的ui消息堵塞造成的。
------解决方案--------------------
用消息是最好的办法。
while( NULL == AfxGetApp()->m_pMainWnd )
{
Sleep( 10 );
}
------解决方案--------------------
MFC 多线程程序有一个重大限制,会影响你所做的几乎每一件事情。MFC
各对象和 Win32 handles 之间的映射关系记录在线程局部存储(Thread LocalStorage,TLS)之中,因此,你没有办法把一个 MFC 对象从某线程手上交到
另一线程手上,你也不能够在线程之间传递 MFC 对象指针。我所谓的 MFC
对象包括(但不限于)CWnd、CDC、CPen、CBrush、CFont、CBitmap、CPalette。
这个限制的存在阻止了“为这些对象产生同步机制”的必要性,那会大大影响
MFC 的速度效率。
这个限制有几个分歧。如果两个线程都调用 CWnd::GetDlgItem() 以取得
对话框中的一个控件(例如 edit),那么每个线程应该获得不同的指针——甚
至即使两个线程的对象是同一个控件。如果面对一个指针,其所指对象并没有
永久的 MFC 结构,那么当对此指针的一个索求行为出现时,MFC 往往会产
生出一些临时性对象。例如,CWnd::GetDlgItem() 往往会在被索求一个指针(例
如指向一个 CEdit* 或一个 CStatic*)时,产生一个临时性对象。这些对象会
在下一次程序进入闲置循环(idle loop)时被清理掉。如果这些对象被许多线
程共享,MFC 就没有能力预期它们的生命,也因此没有能力执行清理工作。
因此,MFC 为每一个有需求的线程产生一个新对象。
这个限制(关于在线程之间交换对象)的意思是说,你不能够放一个指针
(指向一个 CWnd)到结构之中,而该结构被一个 worker 线程使用。你也不
能够把一个指向 CDialog 或 CView 的指针交给另一个线程。当你需要调用
view 或 document 中的一个成员函数,特别是像UpdateAllViews() 这样的函
数时,上述的限制很快便会恶化。
MFC 在许多地方检查“横跨线程之对象的使用情况”。任何时候,只要
MFC 对着对象调用 ASSERT_VALID,它便会检查对象是否保持在线程局部
存储(TLS)中。如果你尝试调用一个像 CDocument::UpdateAllViews() 这样
的函数,那么当程序运行时,CWnd::AssertValid 会产生一个 assertion。下面
的注解来自于 assert 操作之下:
// Note: if either of the above asserts fire and you are
// writing a multithreaded application, it is likely that
// you have passed a C++ object from one thread to another
// and have used that object in a way that was not intended.
// (only simple inline wrapper functions should be used)
------------------------
// In general, CWnd objects should be passed by HWND from
// one thread to another. The receiving thread can wrap
// the HWND with a CWnd object by using CWnd::FromHandle.
//
// It is dangerous to pass C++ objects from one thread to
// another, unless the objects are designed to be used in
// such a manner.
译注 这一段说明出现在 MFC 源代码的 WINCORE.CPP 中的 CWnd::AssertValid()
成员函数内。
线程局部存储(TLS)的使用说明了以 AfxBeginThread() 在 MFC 程序
中产生 UI 线程的重要性。如果你用的是 _beginthreadex() 或 CreateThread()
时,MFC 不会给你机会产生出用以维护其 handles 的必要结构。
在线程之间共享对象,这里倒是有一个不太方便的替代方案:不要放置
MFC 对象,改放对象的 handle。你可以利用 GetSafeHandle() 获得派生自
CGdiObject 的对象的 handle。这样的对象包括 CPen 和 CPalette 对象。你还
可以利用 GetSafeHwnd() 获得派生自 CWnd 的对象的 handle,如CDialog 对
象。
当你把 handle 传递给新线程时,线程可以把该handle 附着到一个新的
MFC 对象:使用 FromHandle() 可以产生一个临时对象,使用 Attach() 则可
以产生一个永久对象。例如,你把一个 HDC 交给线程,你可以利用以下程序
代码把这个 HDC 附着到一个永久的 CDC 对象上:
HDC hOriginalDC = //...
CDC dc;
dc.Attach(hOriginalDC);
而在退出之前,线程应该调用 Detach():
dc.Detach();
296 第二篇 ■ 多线程程序设计的工具与手法
如果线程只是想短暂地使用这个数值,它可以产生一个临时对象,像这样:
CDC *pDC = CDC::FromHandle(hOriginalDC);
并不是所有的 MFC 对象都很容易以该技术传递。CView 就是个例子。
你可以轻易取得一个 view 的窗口 handle,并将它交给一个新线程,但最好这
个新线程可以把此 handle 附着到一个 CWnd 。因为并没有
CView::FromHandle() 函数可以产生一个临时性的 view,像镜子一样反映出原
来的那一个。原来的 CView 结构不再可用,所以所有相关的 view 信息也都
不再可用了。
回到 UpdateAllViews(),此函数运作时所使用的指针被埋藏在 document