Windows消息、绘图与多线程
有一个项目,一旦点下按钮后,用死循环不停的读数据,读出后立刻用可视化的方法显示。
如果不采用多线程的方法,程序运行都正确,但无法关闭窗口,不清楚是窗口无法通过关闭按钮来接受Windows消息,还是接受了消息却没有机会处理?(写个了程序用Spy++观察一下,似乎是没有接受到消息。Delphi IDE可以轻易杀死它,大概是从线程角度杀死的,而不是发消息)
解决方案是:采用多线程。开一个线程读数据,这样主线程仍可用来关闭窗口。但这时候却无法正确显示数据了。原因是Delphi的VCL库不是线程同步的。这时候必须要用TThread的Synchronize来把显示数据的函数同步到主窗口去。注意,这时候不能把读数据的函数也同步进去,这样主程序又无法响应关闭按钮了。应该仅仅同步显示数据的那部分代码。
看来这方面大有讲究,先记下来,以后再补充。代码不贴了,有问题在回复里可以讨论。
另一篇多线程与显示数据的文章:
http://www.cnblogs.com/zhangzhifeng/archive/2011/08/23/2150147.html
他的问题:
DWORD WINAPI ThreadProc(
while(!bTerminate)
{
// 从一个链表中读取信息并且插入到CListCtrl中
// CListCtrl的句柄是通过线程参数传递进来的
for(;;)
{
ReadInfoFromList();
InsertToCListCtrl();
}
}
}
InsertItem的反汇编中发现了如下的代码
call dword ptr [__imp__SendMessageA@16 (7C141B54h)]
可见,InsertItem是必须借助消息循环来完成任务的
解决方案:
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);
}
}
点评:他的意思是,子线程读取数据以后,先要在主窗口上显示数据。然而InsertItem执行的时候把消息发到主窗口去了。然而当开始执行子线程的时候,主窗口就已经处于挂起状态了(因为WaitForSingleObject的原因,无法得到这个唯一的Object所有权,所以主窗口挂起),这样陷入了一个死循环。和我上面那个问题略有不同,但本质一样:子线程想要直接在主窗口显示内容,不同步的话就显示不正确(我的第一个问题),结果要么是同步过头倒是无法响应主线程的其它事件(我的第二个问题),要么是明明主线程挂起了还想让它显示东西(他的第一个问题),而且子线程还等着显示完返回(他的第二个问题),典型的死锁,当然不行。但不知道MFC是不是线程同步的类库?他似乎没有碰到我的第一个问题。
后面的吵架也很有意思,摘录如下:
1. 消息循环只负责获取消息队列中的消息,SendMessageA的消息并不进入消息队列。(点评:正确。但主线程挂起了无法响应是个事实。PostMessage发送的消息是队列消息,它会把消息Post到消息队列中(所以需要等待被处理,因为相对时间长,所以微软把它设计成Post消息后直接返回);SendMessage发送的消息是非队列消息,被直接送到窗口过程处理(一般会立刻直接响应,所以微软把它设计成主线程等待它执行完后才返回)。另外有个问题是,这个SendMessage发生的消息,一旦子线程收到后,会抢在它的队列消息里之前处理吗?如果子线程正在处理某一个消息,是不是至少也要等到当前这个消息处理完才可以处理这个Send来的消息?)
2. SendMessageA发送的消息确实不进入消息循环,但是这个过程是在主线程的上下文中完成的,还是在开的线程中完成的? (点评:问题不是很明确,但发消息是任何线程都有的权力,应该是在子线程中完成发消息的过程)
3. SendMessage的目标窗口如果属于另一个线程,则会发生线程上下文切换,等待另一线程处理完成消息。为了防止另一线程当掉,导致SendMessage永远不能返回,我们可以调用SendMessageTimeout函数(点评:前面的问题属于死锁,可以用Timeout的方法来解决响应问题。但是数据没有显示也是不行的啊,所以TimeOut方法不好)
------------------------------------------------------------------
再来一篇:
当年的某段程序执行时间太长(比如永不休止的外部IO操作),占用了大量CPU资源,却从不放手,会导致其它外部事件/消息无法得到响应(跟我的第一个问题类似,但我的解决方案是多线程,Sleep函数不适用于我的问题),从而出现丢包现象。解决方案:适当加上一个Sleep语句,休眠多少时间自己斟酌(通常100ms也够了)。例子在这里:
http://blog.sina.com.cn/s/blog_5425e1570102e803.html
------------------------------------------------------------------
再来一篇:
PostThreadMessage在线程中应用(以多线程网站数据采集为例)
http://www.cnblogs.com/lwm8246/archive/2011/10/06/2199994.html
PostThreadMessage可帮助线程创建消息队列,但不保证创建成功,需要不停的创建才行。
这篇文章还有一个特点是,次要线程也写了一个while语句来接受和处理自己的线程消息队列,很有意思。
Windows消息、绘图与多线程的更多相关文章
- 【转】windows消息和消息队列详解
转载出处:http://blog.csdn.net/bichenggui/article/details/4677494 windows消息和消息队列 与基于MS - DOS的应用程序不同,Wind ...
- windows消息机制(MFC)
消息分类与消息队列 Windows中,消息使用统一的结构体(MSG)来存放信息,其中message表明消息的具体的类型, 而wParam,lParam是其最灵活的两个变量,为不同的消息类型时,存放数据 ...
- windows消息和消息队列
windows消息和消息队列 转自:http://blog.163.com/zhangjie_0303/blog/static/990827062010113062446767/ 与基于MS - DO ...
- WINDOWS消息和窗口简介
一.WINDOWS的消息和窗口简介:1.什么是windows在这里我就不介绍了,但是作为一个程序员我们要知道WINDOWS最重要的一个也是我们程序员常用的一个东西就是消息.窗口是以消息的形式输入的,窗 ...
- Windows 消息循环(1) - 概览
本文从消息循环是如何驱动程序的这个角度,对 Windows 消息循环进行概览性介绍. 使用 EN5 课件获得更好的阅读体验: [希沃白板5]课件分享 : <Windows培训 - 消息循环> ...
- [转]windows消息机制(MFC)
消息分类与消息队列 Windows中,消息使用统一的结构体(MSG)来存放信息,其中message表明消息的具体的类型, 而wParam,lParam是其最灵活的两个变量,为不同的消息类型时,存放数据 ...
- [译]理解Windows消息循环
出处:http://www.cnblogs.com/zxjay/archive/2009/06/27/1512372.html 理解消息循环和整个消息传送机制对Windows编程来说非常重要.如果对消 ...
- 理解Windows消息循环机制
理解消息循环和整个消息传送机制对Windows编程十分重要.如果对消息处理的整个过程不了解,在windows编程中会遇到很多令人困惑的地方. 什么是消息(Message)每个消息是一个整型数值,如果查 ...
- Windows消息机制
Windows的消息系统是由3个部分组成的: · 消息队列.Windows能够为所有的应用程序维护一个消息队列.应用程序必须从消息队列中获取消息,然后分派给某个窗口.· 消息循环.通过这个循环机制应用 ...
随机推荐
- 关于 Bellman-Ford 与 Floyd 算法的一点感想
在四种常用的最短路算法 Dijkstra, SPFA, floyd, Bellman-Ford 中, Dijks 和 SPFA 的使用较为普遍, 对大多数人来说, 也较为熟悉. 然而, floyd 与 ...
- IntelliJ IDEA导入包的顺序调整和按包类型分类(保持和Eclipse一致)
调整的内容如下: 空行 import java.* 空行 import javax.* 空行 import com.* 空行 import all other imports 空行 import st ...
- scp 时出现permission denied
如果scp到 /usr/local/目录下,则无权限,可更改到用户目录下
- Hierarchical data in postgres
https://coderwall.com/p/whf3-a/hierarchical-data-in-postgres --------------------------------------- ...
- Go语言阅读小笔记,来自知呼达达关于unsafe.Pointer的分享.
第一式 - 获得Slice和String的内存数据 func stringPointer(s string) unsafe.Pointer { p := (*reflect.StringHeader) ...
- odoo 的时差 坑
很多人掉进了odoo的时间坑 odoo约定关于日期的数据,存放在数据库时,以 utc0 时区也就是不带时区 存放,应用程序读取日期展示日期时, 转换成用户的时区展示 例如,stock ...
- 编程算法 - 多重部分和问题 代码(C)
多重部分和问题 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 有n种不同大小的数字a, 每种各m个. 推断能否够从这些数字之中选出若干使它们的 ...
- [GUIDE] How to Setup Ubuntu 16.04 LTS Xenial Xerus for Compiling Android ROMs
With a new version of Ubuntu comes an update to my guide for setting up a build environment to compi ...
- 使用Python处理CSV文件的一些代码示例
笔记:使用Python处理CSV文件的一些代码示例,来自于<Python数据分析基础>一书,有删改 # 读写CSV文件,不使用CSV模块,仅使用基础Python # 20181110 wa ...
- caffe搭建--ubuntu标准平台的搭建
http://caffe.berkeleyvision.org/install_apt.html Ubuntu Installation General dependencies sudo apt-g ...