有一个项目,一旦点下按钮后,用死循环不停的读数据,读出后立刻用可视化的方法显示。
如果不采用多线程的方法,程序运行都正确,但无法关闭窗口,不清楚是窗口无法通过关闭按钮来接受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消息、绘图与多线程的更多相关文章

  1. 【转】windows消息和消息队列详解

    转载出处:http://blog.csdn.net/bichenggui/article/details/4677494  windows消息和消息队列 与基于MS - DOS的应用程序不同,Wind ...

  2. windows消息机制(MFC)

    消息分类与消息队列 Windows中,消息使用统一的结构体(MSG)来存放信息,其中message表明消息的具体的类型, 而wParam,lParam是其最灵活的两个变量,为不同的消息类型时,存放数据 ...

  3. windows消息和消息队列

    windows消息和消息队列 转自:http://blog.163.com/zhangjie_0303/blog/static/990827062010113062446767/ 与基于MS - DO ...

  4. WINDOWS消息和窗口简介

    一.WINDOWS的消息和窗口简介:1.什么是windows在这里我就不介绍了,但是作为一个程序员我们要知道WINDOWS最重要的一个也是我们程序员常用的一个东西就是消息.窗口是以消息的形式输入的,窗 ...

  5. Windows 消息循环(1) - 概览

    本文从消息循环是如何驱动程序的这个角度,对 Windows 消息循环进行概览性介绍. 使用 EN5 课件获得更好的阅读体验: [希沃白板5]课件分享 : <Windows培训 - 消息循环> ...

  6. [转]windows消息机制(MFC)

    消息分类与消息队列 Windows中,消息使用统一的结构体(MSG)来存放信息,其中message表明消息的具体的类型, 而wParam,lParam是其最灵活的两个变量,为不同的消息类型时,存放数据 ...

  7. [译]理解Windows消息循环

    出处:http://www.cnblogs.com/zxjay/archive/2009/06/27/1512372.html 理解消息循环和整个消息传送机制对Windows编程来说非常重要.如果对消 ...

  8. 理解Windows消息循环机制

    理解消息循环和整个消息传送机制对Windows编程十分重要.如果对消息处理的整个过程不了解,在windows编程中会遇到很多令人困惑的地方. 什么是消息(Message)每个消息是一个整型数值,如果查 ...

  9. Windows消息机制

    Windows的消息系统是由3个部分组成的: · 消息队列.Windows能够为所有的应用程序维护一个消息队列.应用程序必须从消息队列中获取消息,然后分派给某个窗口.· 消息循环.通过这个循环机制应用 ...

随机推荐

  1. select函数与stdio混用的不良后果 (转)

    出自:http://www.cppblog.com/mysileng/archive/2013/01/15/197284.html 今天在看UNP6.5节,学习到了select与stdio混用的后果. ...

  2. linux shmget shmctl

    shmgetint shmget(key_t key, size_t size, int flag);key: 标识符的规则size:共享存储段的字节数flag:读写的权限返回值:成功返回共享存储的i ...

  3. LeetCode OJ--Minimum Path Sum **

    https://oj.leetcode.com/problems/minimum-path-sum/ 对一个grid从左上角到右下角的路径,求出路径中和最小的. 受之前思路的影响,就寻思递归,并且记录 ...

  4. window.getComputedStyle——ref

    componentDidMount() { const LeftHeight = window.getComputedStyle(this.leftDom).height; console.log(L ...

  5. Codechef Eugene and big number(矩阵快速幂)

    题目链接 Eugene and big number 题目转化为 $f(n) = m * f(n - 1) + a$ $f(n + 1) = m * f(n) + a$ 两式相减得 $f(n + 1) ...

  6. Codeforces Gym 100338C Important Roads 最短路+Tarjan找桥

    原题链接:http://codeforces.com/gym/100338/attachments/download/2136/20062007-winter-petrozavodsk-camp-an ...

  7. luogu P1057 传球游戏

    题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏.这次,老师带着同学们一起做传球游戏. 游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹哨子时开始传球,每个同 ...

  8. mysql function

    mysql 自定义函数的使用 先查看函数功能是否开启:show variables like '%func%'; 若是未开启则:SET GLOBAL log_bin_trust_function_cr ...

  9. Leanote 二进制版详细安装教程 Windows

    https://github.com/leanote/leanote/wiki 本教程适合 Windows 用户的二进制版安装. Windows 用户的源码版安装,参见这里. Mac, Linux 用 ...

  10. Jenkins Robot framework 持续集成环境搭建

    为什么我们要引入RF?其实最初我们引入RF是为了能够快速的开展自动化验收测试,为敏捷保驾护航.这其中有个重要的工具Jenkins,同时也是应群里朋友们的要求,这次就来介绍一下RF如何快速便捷的结合Je ...