线程中创建非模式对话框

yanglovexian 2008-08-26 03:20:34
我在WinCE下线程中用
pDlg->m_pDlgScreenMap = new CScreenMap();
pDlg->m_pDlgScreenMap->Create(IDD_DIALOG_SCREENMAP,NULL);
pDlg->m_pDlgScreenMap->ShowWindow(SW_SHOW);
pDlg->m_pDlgScreenMap->UpdateWindow();
创建对话框,结果出现异常
异常的地方在:
CHandleMap* pMap = afxMapHWND();
ASSERT(pMap != NULL);

CObject* p;
ASSERT((p = pMap->LookupPermanent(m_hWnd)) != NULL ¦ ¦
(p = pMap->LookupTemporary(m_hWnd)) != NULL);
ASSERT((CWnd*)p == this); // must be us
...全文
485 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
yanglovexian 2008-08-28
  • 打赏
  • 举报
回复
谢谢clever101我做出来了
clever101 2008-08-27
  • 打赏
  • 举报
回复
quote:有几种方式可以避免此问题。首先是将各个句柄(如 HWND)而不是 C++ 对象传递到辅助线程。然后,辅助线程通过调用适当 FromHandle 成员函数将这些对象添加到它的临时映射。还可以通过调用 Attach 将对象添加到线程的永久映射,但只有在保证对象比线程存在的时间长时,才应当进行此操作。


如果按照这种说法,我说的做法还是可行的,因为视图类对象或框架类对象一般比线程存在的时间长嘛。
hurry281 2008-08-27
  • 打赏
  • 举报
回复
if(pDlg->m_pDlgScreenMap == NULL)
{
pDlg->m_pDlgScreenMap = new CScreenMap();
pDlg->m_pDlgScreenMap->Create(IDD_DIALOG_SCREENMAP,NULL);
pDlg->m_pDlgScreenMap->ShowWindow(SW_SHOW);
pDlg->m_pDlgScreenMap->UpdateWindow();
}
else
{
delete pDlg->m_pDlgScreenMap;
pDlg->m_pDlgScreenMap = new CScreenMap();
pDlg->m_pDlgScreenMap->Create(IDD_DIALOG_SCREENMAP,NULL);
pDlg->m_pDlgScreenMap->ShowWindow(SW_SHOW);
pDlg->m_pDlgScreenMap->UpdateWindow();
}
clever101 2008-08-27
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 yanglovexian 的回复:]
请问你有例子吗,我是新手,不太明白,谢谢
[/Quote]

详细例子参考:http://blog.csdn.net/clever101/archive/2008/08/27/2840174.aspx
菜牛 2008-08-27
  • 打赏
  • 举报
回复
我估计你的线程不是从CWinThread继承的,所以缺少线程管理MFC类的一些功能。试试从CWinThread继承线程类。
yanglovexian 2008-08-27
  • 打赏
  • 举报
回复
请问你有例子吗,我是新手,不太明白,谢谢
菜牛 2008-08-27
  • 打赏
  • 举报
回复
Visual C++ 概念:添加功能

多线程编程:编程提示


访问数据时,使用多线程应用程序比使用单线程应用程序要更加小心。因为在多线程应用程序中同时有多个独立的执行路径正在使用,算法或数据或两者都必须注意:可以有一个以上的线程同时使用数据。此文章解释了在使用 Microsoft 基础类库 (MFC) 编制多线程应用程序时避免发生潜在问题的技术。

从多线程访问对象
从非 MFC 线程访问 MFC 对象
Windows 句柄映射
线程间通信
从多线程访问对象
由于大小和性能原因,MFC 对象在对象级别不是线程安全的,而只是在类级别线程安全。这表明可以有两个独立的线程操作两个不同的 CString 对象,但不能有两个线程操作同一个 CString 对象。如果一定要有多个线程操作同一个对象,请用适当的 Win32 同步机制(如临界区)保护此类访问权。有关临界区和其他相关对象的更多信息,请参见 Platform SDK 中的同步。

类库内部使用临界区以保护全局数据结构,例如调试存储分配使用的结构。

从非 MFC 线程访问 MFC 对象
如果多线程应用程序使用 CWinThread 对象以外的方式创建线程,则不能从该线程访问其他 MFC 对象。换句话说,如果要从次要线程访问任何 MFC 对象,则必须用多线程编程:创建用户界面线程或多线程编程:创建辅助线程文章中所述的方法之一创建该线程。只有这些方法才允许类库初始化处理多线程应用程序所需的内部变量。

Windows 句柄映射
作为通用规则,线程只能访问它创建的 MFC 对象。这是因为临时和永久性 Windows 句柄映射保留在线程本地存储中,以对它进行保护,确保不能有多个线程同时访问它。例如,辅助线程不能执行计算并调用文档的 UpdateAllViews 成员函数来修改包含新数据视图的窗口。此操作将不会有任何效果,因为从 CWnd 对象到 HWND 的映射是主线程的本地映射。这意味着一个线程可能有从 Windows 句柄到 C++ 对象的映射,但是另一个线程可能会将此句柄映射到其他 C++ 对象。在一个线程内所做的更改将不会反映在另一个线程中。

有几种方式可以避免此问题。首先是将各个句柄(如 HWND)而不是 C++ 对象传递到辅助线程。然后,辅助线程通过调用适当 FromHandle 成员函数将这些对象添加到它的临时映射。还可以通过调用 Attach 将对象添加到线程的永久映射,但只有在保证对象比线程存在的时间长时,才应当进行此操作。

另一个方法是创建新的与辅助线程将要执行的不同任务相对应的用户定义消息,并使用 ::PostMessage 将这些消息发布到应用程序的主窗口。此通信方法类似于两个不同的应用程序在对话,只不过这两个线程在同一地址空间中执行。

有关句柄映射的更多信息,请参见技术说明 3。有关线程本地存储的更多信息,请参见 Platform SDK 中的线程本地存储和使用线程本地存储区。

线程间通信
MFC 提供了多个类,使线程可以同步访问对象以维护线程安全。多线程编程:如何使用同步类和多线程编程:何时使用同步类文章中描述了这些类的用法。有关这些对象的更多信息,可在 Platform SDK 的同步中找到。

请参见
使用 C++ 和 MFC 进行多线程编程

clever101 2008-08-26
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 Mackz 的回复:]
MFC对象最好不要跨线程。
[/Quote]

大虾,为什么MFC对象最好不要跨线程呢?
菜牛 2008-08-26
  • 打赏
  • 举报
回复
MFC对象最好不要跨线程。
clever101 2008-08-26
  • 打赏
  • 举报
回复
1. 在线程中不适宜直接使用对话框的,一般会出错。

2. 我推荐的做法是转递视图窗口句柄(注意不是视图窗口指针给线程,在多线程程序中不能传窗口指针的,只能传窗口句柄进去,再在里面通过句柄获取窗口指针),在线城获取数据,然后发消息给视图类,在视图类里自定义消息函数创建对话框,当然这里把视图类换为框架类也可以。


cqruan 2008-08-26
  • 打赏
  • 举报
回复
这是VC6的,看看对你有没有帮助.

(1)对象调用:

定义对话框全局对象的变量,
CTestDlg dlg;
dlg.Create(IDD_DIAALOG1,NULL/*this*/);//如果是NULL,则对话框属于应用程序所有,
//如果是this,属于当前调用的窗口所有;
dlg.ShowWindow(SW_SHOW);

注意:如果定义为局部变量,非模态对话框是显示不出来的,因为调用他的那个过程执行到}的时候
局部变量的所有属性都被销毁,所以显示不出来


(2)指针调用
CTestDlg *pDlg=new CTestDlg();
pDlg->Create(IDD_DIALOG1,this);
pDlg->ShowWindow(SW_SHOW);

注意:如果定义为局部指针,当程序执行到}即生命周期结束的时候,他所保存的内存地址就丢失了,
我们就没法在对他的引用,所以,也要进行全局定义,在析构函数中 把整个指针删除。


当在非模态对话框中执行,CDialog::OnOK();时是对话框被隐藏了,并没有被销毁,而模态对话框是
销毁对话框,其实 在模态对话框中 调用 CDialog::OnOK();
其实是调用了基类的CDialog::EndDialog();这个函数只实用于模态对话框,所以在非模态对话框中不要调用基类的CDialog::OnOK(),CDialog::EndDialog();方法,必须重载这两个方法,并把基类的CDialog::OnOK(),CDialog::EndDialog();方法注释掉,如果确实要销毁一个非模态对话框就用:
DestroyWindow()方法,但是在这之前,如果有必要,必须调用UpdateData(TRUE)把数据保存到变量中,然后再调用DestroyWindow()方法。
yanglovexian 2008-08-26
  • 打赏
  • 举报
回复
没人会吗,我很急,希望有人回答!!谢谢

16,467

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧