窗口和线程漫谈之工作线程如何将数据的处理结果显示到窗口

原创 2015年07月08日 15:54:26

前言

原本这篇博客的标题叫《窗口和线程漫谈》,但想来想去确实不太合适,因为我确实没有写关于窗口和线程的任何理论知识,而只是探讨了工作线程如何将数据的处理结果显示到窗口这个问题,因此重新修改标题。

另外,关于窗口和线程的相关理论知识,感觉一两句话确实说不清楚,而且《Windows 核心编程》这本书上介绍的也挺好的,有机会再写吧。特别是感觉现在好多人都直接在学 MFC,用 MFC,甚至连窗口过程,消息循环都不太明白,如果能有这样一篇博客也是很有价值的。

为什么要讨论这个问题

讨论这个依然是跟之前的项目经历有关。这里暂且称该项目为 A 项目。A 项目包括一个客户端和服务端,客户端有一个核心的网络模块,该网络模块基于完成端口开发,有多个工作线程,网络模块负责接收来自服务端的数据,对这些数据进行处理,并将最终的处理结果显示在窗口上。那么问题来了,工作线程如何将数据的最终处理结果显示在窗口上?可以说这个问题不仅仅是 A 项目中遇到的问题,绝大多数网络应用程序都会遇到这个问题。当时 A 项目中采用的方案是在工作线程中利用窗口句柄直接调用相应函数(如 SendMessage)对窗口进行操作。虽然这种做法当时并没有出现问题?但它真的没问题吗?如果有问题,我们该采用什么方式将最终的处理结果显示在窗口上呢?

窗口和线程的关系

理论知识是我们回答上述问题的基础。这方面我找到的唯一资料就是 《Windows 核心编程》 第 26 章 窗口消息。对这块不太明白的兄弟,可以先看下。这里我们就不详述了。

在工作线程中利用窗口句柄直接调用相应函数对窗口进行操作这种做法有没有问题

绝大多数情况下,确实不会出现问题。但只是绝大多数情况下,下面是出现问题的两种情况。

  1. 这种情况是我在项目 A 中亲身经历的。当时我在工作线程中调用了 SetFocus 这个函数,结果这个函数并没有成功返回,为什么?下面是 SetFocus 文档中的描述。

    Sets the keyboard focus to the specified window. The window must be attached to the calling thread’s message queue.

    原因很明显,传递给 SetFocus 函数的窗口句柄代表的窗口必须是属于调用 SetFocus 函数的这个线程的,但工作线程并没拥有该窗口,也没有拥有任何窗口。那为什么调用 SetFoucs 函数要有这个需求呢?这个只能说我也不太清楚,但结合 《Windows 核心编程》 第 26 章 中的相关描述,每一个线程都拥有自己的键盘焦点,应该在一定程度上回答了这个问题。

  2. 这种情况是《多线程编程中的主界面安全处理》这篇文章中提到的,大致情况就是拥有窗口的线程正在等待工作线程退出,而工作线程正阻塞于对窗口的 SendMessage 调用中。应该说,这种情况不是没有可能发生。

说了这么多,说到底我是不建议在工作线程中利用窗口句柄直接调用相关函数对窗口进程操作这种做法的,虽然这种做法绝大多数情况下不会出错,但一旦出现问题,排查起来就比较困难。但我也不完全否认这种做法,前提是,程序员自身一定要对程序本身的逻辑认识清楚,比如在工作线程中会不会调用类似 SetFocus 的这类函数,会不会出现上面提到的第二种情况。

工作线程如何将最终的处理结果显示到窗口

既然,在工作线程中通过窗口句柄直接调用相关函数对窗口进行操作的这种做法不太好,那采用什么方法将最终的处理结果显示到窗口上呢?我的方法是调用 PostMessage,通过自定义消息将数据交给窗口的窗口过程处理,也就是拥有窗口的线程处理,这种情况下工作线程中唯一和窗口相关的操作就是通过窗口句柄调用 PostMessage。目前,我并想不到这种做法有什么有问题的地方,如果有人觉得有问题,大家可以一起讨论下。

另外,如果有兄弟知道更好的做法,大家也可以讨论下。

感受和思考

在查找线程和窗口的相关资料过程中,发现很多人都在问关于线程和窗口的一些问题,在讨论关于窗口和线程的一些概念,而且搞出来一些很玄乎的东西。但其实搞清楚一些基础知识,自己独立思考一下,这些问题并不难回答。也许 MFC 相对传统的 Win32 API 确实方便些,但窗口过程,消息循环等一些基本概念还是要理解的。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

MFC编辑框自动滚动到最后一行

MFC编程中需要将编辑框中数据自动换行,并且添加垂直滚动条,首先在界面属性里面设置如下: 设置好之后,当编辑框内的数据超出显示范围的时候,就会自动滚行,但是一直显示的是顶行的数据,需要手动拉...

[MFC]在程序中访问对话框中的控件——GetDlgItem函数

1. 使用GetDlgItem函数来访问对话框中的控件:     1) 函数原型:CWnd* CWnd::GetDlgItem(int nID) const;     2) 只要参数指定为要访问的控件...

MFC 窗口句柄获取

句柄获取方法(获取该窗口的句柄后,即可向该窗口类类发送消息、处理程序):0。获取所在类窗口的句柄: this->m_hwnd 1。主窗口的句柄: 无论在主窗口类内,还是子窗口类内,获取主窗口句柄...

MFC中如何获取编辑框内容的两种形式

1、设置编辑框变量   在MFC的基本对话框中,我建立了一个编辑框控件,变量名为 m_Min ,类型为value int 现在我想获取这个控件中的内容,并存入类型为int的变量temp中,请问怎么样...

MFC多线程的创建,包括工作线程和用户界面线程

MFC多线程的创建 1.MFC多线程简介 MFC对多线程进行了一层简单的封装,在Visual C++中每个线程都是从CWinThread类继承而来的。每一个应用程序的执行都有一个主线程,这个主线程...

MFC CInternetSession

VC: #include "afxinet.h" #include CString url ("http://localhost/web?cmd=start&sn=123456&ai=abcd...

MFC 界面线程和工作者线程

MFC 界面线程和工作者线程   每个系统都有线程,而线程的最重要的作用就是并行处理,提高软件的并发率。针对界面来说,还能提高界面的响应力。  线程分为界面线程和工作者线程,界...

MFC多线程各种线程用法 .

一、问题的提出 编写一个耗时的单线程程序:   新建一个基于对话框的应用程序SingleThread,在主对话框IDD_SINGLETHREAD_DIALOG添加一个按钮,ID为 IDC_...

在MFC中从一个线程工作函数中向窗口发送消息(this指针的妙用)

前一段时间使用MFC写程序的时候,为了实现从一个窗口向另一个窗口发送消息,使用过下面两种方法 /*方法一:通过用SDK的标准API来查找其他对话框窗口返回句柄,并且发送信息 HWND hWnd; ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)