关闭对话框结束线程

ddgg18 2009-05-07 03:47:34
在对话框的OnInitdialog()中创建一个线程,在关闭时置一个变量为TRUE,在线程中检测为TRUE,直接return;
在关闭时Waitforsingleobject那个线程,然后就一直堵塞在这了,在线程中设断点也跟踪不到,不知执行到哪吧,高手请指点迷津
...全文
400 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
ddgg18 2009-05-14
  • 打赏
  • 举报
回复
问题现象:
在主线程中设置bStopNow标志,WaitForSingleObject(threadHandle, INFINITE);
线程马上就死掉了!!!通过调试信息输出,看到线程可能停止在while循环的任意位置。

问题原因:
因为本程序涉及向ListCtrl控件中添加记录。
我在InsertItem的反汇编中发现了如下的代码
call dword ptr [__imp__SendMessageA@16 (7C141B54h)]
可见,InsertItem是必须借助消息循环来完成任务的。如果我们在主线程中WaitForSingleObject了,必然导致主线程阻塞,也就导致了消息循环的阻塞,最终导致工作线程Crash掉了*_*

总结:
如果在工作线程中有可能涉及到了消息驱动的API,那么不能在主线程中使用WaitForSingleObject一类函数,而必须使用下述的方案:
while(TRUE)
{

DWORD result ;
MSG msg ;

result = MsgWaitForMultipleObjects(1, &readThreadHandle,
FALSE, INFINITE, QS_ALLINPUT);

if (result == (WAIT_OBJECT_0))
{
break;
}
else
{
PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
DispatchMessage(&msg);
}
}
或者14楼方案。
mqiezi 2009-05-11
  • 打赏
  • 举报
回复
线程同步的问题,子线程在傻等
hwsts2 2009-05-10
  • 打赏
  • 举报
回复
同意 11楼
野男孩 2009-05-09
  • 打赏
  • 举报
回复
ThreadPro线程被挂住了,或者没有走到检查那个变量的逻辑上。

比如POSITION pos = fileList.GetTailPosition(); 如果pos为空,则不会走到里面检查if(bStopNow)的地方。
Lin 2009-05-08
  • 打赏
  • 举报
回复
俺给个建议:
void CdlgOpera::OnCancel()
{
...
KillTimer(1);
bStopNow = TRUE;//结束线程
DWORD dwResult;
GetExitCodeThread(m_hThread, &dwResult);
if (dwResult != 0)
{
WaitForSingleObject(m_hThread, INFINITE); //死在这
}
CloseHandle(m_hThread);
.......
}

可以修改一下:
if (dwResult != 0)
{
while (WaitForSingleObject(m_hThread, 0) != WAIT_OBJECT_0)
{
MSG msg; //这里增加消息处理函数,让线程还能得到执行的机会
while(::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (!AfxGetThread()->PumpMessage() break;
}
}
}


你可以试下
wutaihua 2009-05-08
  • 打赏
  • 举报
回复
不要阻塞主线程。Waitforsingleobject在主线程中一定会阻塞主线程。
你应该在子线程中Waitforsingleobject()一个事件。当退出的时候,直接把事件置为有信号的状态。这样线程就退出了。
也可以在子线程中PeekMessage()当得到WM_QUIT这个消息的时候,就退出来。
bobohack 2009-05-08
  • 打赏
  • 举报
回复
可以用事件控制线程退出 线程每次循环一次看这个事件到没有,如果到则线程退出

WaitForSingleObject( 事件 ,0);
cnzdgs 2009-05-07
  • 打赏
  • 举报
回复
线程互锁了,常见的原因是:线程中要访问主线程的窗口(或窗口中的控件),因为访问窗口实际上是通过SendMessage由窗口所属线程来处理的,而主线程此时在等待另一个由线程触发的事件(线程结束),而没有取消息,所以线程一直在等待主线程处理消息而不会结束,结果就是两个线程永远等待。
建议解决办法:主线程在设置标志通知线程结束之后立即返回,线程在退出前给窗口发送一个自定义消息,主线程响应这个消息关闭窗口(无须等待线程结束)。
捕鲸叉 2009-05-07
  • 打赏
  • 举报
回复
没做过等待线程句柄的,莫非线程已退出,线程句柄已失效,却一直在等它?
  • 打赏
  • 举报
回复
为什么需要Waitforsingleobject
ddgg18 2009-05-07
  • 打赏
  • 举报
回复
里面你用主线程等待子线程,等不到的话就会挂起自己
应该怎么做?
biweilun 2009-05-07
  • 打赏
  • 举报
回复
void CdlgOpera::OnCancel()
{
...
KillTimer(1);
bStopNow = TRUE;//结束线程
DWORD dwResult;
GetExitCodeThread(m_hThread, &dwResult);
if (dwResult != 0)
{
WaitForSingleObject(m_hThread, INFINITE); //死在这
}
CloseHandle(m_hThread);
.......
}
里面你用主线程等待子线程,等不到的话就会挂起自己
ddgg18 2009-05-07
  • 打赏
  • 举报
回复
void CdlgOpera::AddToDownLoadList()这个函数是线程ThreadPro里调用的一个函数
ddgg18 2009-05-07
  • 打赏
  • 举报
回复
汗,公司使用虚拟机上网,不能考代码,而且输入法还是紫光的,的打半天。。。。
BOOL CdlgOpera::OnInitDialog()
{
....
LPVOID lpvoid = this;
m_hThread = CreateThread(NULL, 0, ThreadPro, lpvoid, Create_SUSPENDED, 0);
...
ResumeThread(m_hThread);
.....
}

void CdlgOpera::OnCancel()
{
...
KillTimer(1);
bStopNow = TRUE;//结束线程
DWORD dwResult;
GetExitCodeThread(m_hThread, &dwResult);
if (dwResult != 0)
{
WaitForSingleObject(m_hThread, INFINITE); //死在这
}
CloseHandle(m_hThread);
.......
}

void CdlgOpera::AddToDownLoadList()
{
......
POSITION pos = fileList.GetTailPosition();
while(pos)
{
sLine = fileList.GetPrev(pos);
i++;
TRACE("Stop:%d\n%d\n", i, bStopNow);
if(bStopNow)
{
TRACE("STOP!\n");
return;
}
.......
}
.....
}
最后可见的调试信息为:
Stop:242
0
就是没有STOP!
跟踪也跟不到,迷惑
aa3000 2009-05-07
  • 打赏
  • 举报
回复
有可能死锁,贴代码吧
m_tornado 2009-05-07
  • 打赏
  • 举报
回复
该不是主线程等子线程,子线程等主线程吧,怕是锁住了:)
biweilun 2009-05-07
  • 打赏
  • 举报
回复
调试看看你的线程句柄是否还存在,有没有自我销毁。贴出点代码看看
biweilun 2009-05-07
  • 打赏
  • 举报
回复
不要在主线程中Waitforsingleobject,创建一个线程另外监视,这样可以防止主线程堵塞
目录 第1章 面向对象编程 1.1 面向对象的基本概念 1.1.1 类和对象 1.1.2 封装、多态和继承 1.1.3 消息 1.2 面向对象的建模技术UML 1.2.1 类图 1.2.2 交互图 1.2.3 用例图 1.3 面向对象的C++语言 1.3.1 C++对象的内存布局 1.3.2 C++编程技术要点 1.4 小结 第2章 窗口 2.1 窗口结构 2.2 窗口类型 2.3 窗口关系 2.4 消息和消息处理 2.4.1 系统定义的消息 2.4.2 应用程序定义的消息 2.4.3 消息参数 2.4.4 消息队列 2.4.5 消息循列 2.4.6 窗口过程 2.5 窗口应用框架 2.6 小结 第3章 MFC简介 3.1 MFC的优势 3.2 MFC中的类 3.3 用MFC开发应用的基本方法 3.4 MFC中的窗口管理 3.4.1 C++窗口对象和Windows窗体之间的关系 3.4.2 创建窗口 3.4.3 销毁窗体 3.4.4 定位窗体 3.4.5 绘图 3.4.6 消息处理 3.5 小结 第4章 CObject类 4.1 概述 4.2 创建对象 4.2.1 直接构造 4.2.2 使用new操作符 4.3 诊断功能 4.3.1 Dump成员 4.3.2 AssertValid 4.4 运行时类信息 4.4.1 CRuntimeClass结构 4.4.2 添加运行时类信息 4.4.3 IsKindOf 4.5 动态创建 4.6 序列化 4.6.1 添加序列化支持 4.6.2 CArchive类 4.6.3 对象序列化实例 4.7 小结 第5章 MFC应用框架 5.1 应用程序对象和MFC类库的交互 5.2 应用程序的初始化 5.3 消息循环 5.4 空闲处理 5.5 应用程序的退出 5.6 CWinApp提供的其他服务 5.6.1 外壳程序注册 5.6.2 文件管理器拖放 5.6.3 跟踪最近使用的文档 5.7 小结 第6章 消息映射 6.1 基本概念 6.2 消息映射表 6.3 一般窗口消息的处理成员的定位 6.4 命令处理成员的定位 6.5 消息映射宏 6.5.1 窗口映射宏 6.5.2 命令映射宏 6.5.3 控制通知消息映射宏 6.5.4 通知消息映射宏 6.5.5 反射消息映射宏 6.6 小结 第7章 消息处理 7.1 处理标准窗口消息 7.1.1 处理WM_CREATE消息 7.1.2 处理WM_DESTROY消息 7.1.3 处理WM_NCDESTORY消息 7.1.4 处理WM_CLOSE消息 7.2 处理命令消息 7.3 处理反射消息 7.4 投递和发送消息 7.4.1 投递和发送消息的概念 7.4.2 postMessage函数 7.4.3 SendMessage函数 7.4.4 SendMessage 7.5 SendNotifymessage和SendMessageCallback 7.6 使用自定义命令 7.7 使用自定义窗口消息 7.8 使用登记消息 7.9 处理线程消息 7.10 跨进程处理消息 7.11 消息钩子 7.11.1 钩子和过滤器 7.11.2 钩子的类型和范围 7.11.3 安装和解除消息钩子 7.11.4 使用线程范围和钩子实例 7.11.5 使用全局钩子实例 7.12 小结 第8章 对话框 8.1 对话框的生存期 8.1.1 对话框的创建 8.1.2 对话框的初始化 8.1.3 对话框的消息处理 8.1.4 对话框结束 8.2 数据交换和数据验证 8.3 使用通用对话框 8.3.1 基本用法 8.3.2 定制通用对话框 8.4 运行时修改对话框 8.5 作为子窗口的对话框 8.6 HTML对话框 8.6.1 HTML资源 8.6.2 让HTML全部可见 8.6.3 混合HTML元素和窗口控件设计对话框 8.6.4 HTML消息处理 8.6.5 HTML元素和对话框成员间的数据交换 8.6.6 导航 8.6.7 基于HTML对话框的实用实例 8.7 使用属性表 8.8 使用对话栏 8.8.1 创建 8.8.2 销毁 8.8.3 处理控件消息 8.8.4 访问对话栏成员 8.8.5 实例 8.9 小结 第9章 文档和视图 9.1 文档/视图结构 9.1.1 原理 9.1.2 为什么使用文档/视图结构 9.1.3 基于文档/视图结构的应用 9.2 文档/视图结构的创建 9.2.1 文档模板的创建 9.2.2 文档的创建 9.2.3 框架的创建 9.2.4 视图的创建 9.2.5 文档/视图的初始化 9.3 深入文档模板 9.3.1 文档模板管理器 9.3.2 文档模板的创建 9.3.3 管理文档 9.3.4 其他 9.4 文档对象 9.4.1 文档的初始化 9.4.2 保存文档 9.4.3 设置修改标志和保存修改 9.4.4 关闭文档 9.4.5 管理视图 9.4.6 文档的销毁 9.4.7 命令处理 9.4.8 文档的序列化 9.4.9 设计文档的成员 9.5 视图对象 9.5.1 视图的初始化 9.5.2 视图和文档间的数据交换 9.5.3 视图的绘制 9.5.4 视图的销毁 9.6 框架窗口 9.6.1 初始化 9.6.2 和文档的交互 9.6.3 和视图的交换 9.6.4 命令处理 9.6.5 确定视图大小 9.6.6 为框架添加其他子控件 9.7 打印 9.7.1 文档/视图框架中的打印流程 9.7.2 自定义打印 9.7.3 打印预览 9.8 小结 第10章 深入视图 10.1 拆分 10.1.1 视图的创建 10.1.2 拆分窗口的命令处理 10.1.3 对拆分子窗口的管理 10.1.4 绘制 10.2 流动和缩放 10.2.1 滚动 10.2.2 缩放视图 10.3 控件视图 10.4 窗体视图 10.5 基于HTML的视图——CDHtmlView 10.5.1 加载HTML 10.5.2 事件处理 10.5.3 在新的文档中打开HTML 10.6 小结 第11章 GDI绘图 11.1 GDI绘图的编程模型 11.1.1 逻辑空间和设备空间 11.1.2 设备上下文 11.1.3 GDI对象 11.1.4 坐标变量和坐标映射 11.2 绘制图形 11.2.1 画线 11.2.2 绘制矩形 11.2.3 绘制椭圆 11.2.4 绘制弧线 11.2.5 绘制多边形 11.2.6 绘制贝济埃样条 11.2.7 使用路径 11.2.8 填充 11.2.9 区域 11.3 使用图像 11.3.1 位图的结构 11.3.2 位图类型 11.3.3 图像初始化和销毁 11.3.4 从文件加载图像文件 11.3.5 将图像保存为文件 11.3.6 图像的显示、裁剪和缩放 11.3.7 图像处理 11.4 小结 第12章 GDI+绘图 12.1 GDI+编程模型 12.1.1 GDI+的组成 12.1.2 GDI+的功能 12.1.3 GDI+编程步骤 12.1.4 新增功能 12.2 绘制基数样条曲线 12.3 独立的路径对象 12.4 Alpha混合 12.4.1 在钢笔中应用Alpha混合 12.4.2 在画刷中应用Alpha混合 12.4.3 对图像应用Alpha混合 12.5 渐变 12.5.1 线性渐变 12.5.2 轨迹渐变 12.6 变换和矩形对象 12.7 使用图像 12.8 小结 第13章 进程和线程 13.1 基本理论 13.1.1 什么是进程 13.1.2 什么是线程 13.1.3 进程地址空间 13.1.4 线程的生命周期 13.2 创建子进程 13.3 虚拟内存管理 13.4 进程间内存共享 13.5 用户界面线程 13.5.1 创建 13.5.2 退出 13.5.3 线程间通信 13.6 辅助线程 13.6.1 创建 13.6.2 退出 13.6.3 线程间通信 13.7 线程安全措施 13.7.1 需要采取线程安全措施的对象 13.7.2 线程安全的实现 13.8 小结 第14章 动态链接库 14.1 简介 14.1.1 DLL的构成 14.1.2 到DLL的链接 14.1.3 DLL映射到进程空间 14.1.4 使用动态链接的好处 14.2 规则DLL创建及其使用 14.2.1 创建规则DLL 14.2.2 规则DLL的使用 14.2.3 输出全局变量 14.2.4 输出类 14.2.5 输出进程间共享的数据 14.3 进程状态、模块状态和线程状态 14.3.1 线程局部存储 14.3.2 模块状态 14.4 创建和使用扩展DLL 14.4.1 创建 14.4.2 使用 14.5 DLL中的资源 14.5.1 资源的名字和类型 14.5.2 确定定义资源的模块 14.5.3 在模块中查找、加载资源 14.5.4 枚举资源 14.5.5 修改可执行文件的资源 14.5.6 纯资源DLL 14.5.7 附属DLL 14.6 小结 第15章 COM组件编程 15.1 COM基础知识 15.1.1 COM中的接口 15.1.2 COM对象的线程模型 15.1.3 进程内组件和进程间组件 15.1.4 COM库 15.1.5 COMK 的功能复用 15.2 IUnknown接口在MFC中的实现 15.2.1 内部类 15.2.2 接口映射类 15.2.3 聚合的实现 15.3 类厂及其MFC实现 15.3.1 ColeObjectFactory类 15.3.2 全局类厂链 15.3.3 类厂的注册/反注册 15.3.4 类厂对象的创建 15.3.5 类厂对象创建COM对象 15.3.6 为CCmdTarget添加类厂支持 15.4 用MFC实现简单的COM组件 15.4.1 创建支持自动化的规则DLL 15.4.2 定义接口文件 15.4.3 实现被聚合的COM组件 15.4.4 实现包容组件 15.4.5 编译、注册COM组件 15.4.6 创建一个对话框应用 15.5 双重接口 15.5.1 调度表 15.5.2 COleDispatchImpl 15.5.3 m_xDispatch成员 15.5.4 输出IDispatch接口 15.5.5 双重接口的客户端 15.5.6 范例 15.6 可连接对象及其MFC实现 15.6.1 用CCmdTarget实现可连接对象 15.6.2 可连接对象的客户端 15.7 封送的应用:在线程间传递接口指针 15.8 小结 第16章 .NET应用开发 16.1 C++托管扩展简介 16.1.1 什么是.NET平台 16.1.2 托管C++中的类型 16.1.3 托管C++的用途 16.1.4 为什么MFC应用添加托管支持 16.1.5 使用.NET类型 16.1.6 实例:创建手管类型 16.1.7 装箱:值类型到引用类型的转化 16.1.8 托管类型和非托管类型的混用 16.1.9 固定指针 16.2 常用的托管C++编程技能 16.2.1 声明托管类 16.2.2 声明值类型的托管类型 16.2.3 添加属性 16.2.4 定义及实现接口 16.2.5 托管数组 16.2.6 处理异常 16.2.7 定义和使用委托 16.2.8 创建对象 16.2.9 对象的序列化和反序列化 16.2.10 用ADO.NET访问数据库 16.2.11 断方和条件编译 16.3 具有双重接口功能的规则DLL 16.4 典型托管应用开发 16.4.1 控制台应用 16.4.2 类库应用 16.4.3 窗体应用 16.5 小结

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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