编程环境
编程平台: Visual Studio 2013
框架:MFC
操作系统:Windows 10
第一步:建立一个MFC界面程序
- 新建工程,选择“MFC”,设置好工程名MFCApplication1和保存路径;
- 选择“基于对话框”,下一步
-
一直选择下一步,直到完成。然后VS自动给建立了一个名为“MFCApplication1”的工程。
-
在工程属性中,设置字符集为“多字节字符集”。不设置的话,某些地方会提示有错误。
第二步:新建两个线程,线程A和线程B
说明:
- 线程A创建后不启动,线程B创建后马上启动;
- 事件内核对象创建时,状态为“未置信”;
- 界面上添加一个按钮“开启线程A”,用于启动线程A,里面代码为:
ResumeThread(hThreadA);
-
线程A开启后,它的函数体中,将事件内核对象“置信”;
-
线程B中,一直等待事件内核对象,当事件内核对象为“置信时”,弹窗“大家好,我叫线程B。谢谢线程A把我叫醒!”;
-
关闭弹窗后,线程B会退出。
-
在头文件MFCApplication1Dlg.h中,在类的定义中,声明线程处理函数,即线程入口
public:
static DWORD __stdcall ThreadFuncA(LPVOID pParam);// Thread A
static DWORD __stdcall ThreadFuncB(LPVOID pParam);// Thread B
- 在MFCApplication1Dlg.cpp文件中,在开头部分添加线程句柄和ID的声明:
HANDLE hThreadA;A线程句柄
HANDLE hThreadB;B线程句柄
DWORD dwThreadIdA; 线程A的ID
DWORD dwThreadIdB; 线程B的ID
HANDLE g_hEvent;//事件内核对象的句柄
#define EventObjName "eventName"//事件名称
- 在MFCApplication1Dlg.cpp文件中,找到对话框初始化函数,添加创建线程代码:
创建线程A//
hThreadA = CreateThread(NULL,/* 使用默认的安全属性 */
100, /* 线程堆栈控件的大小 */
ThreadFuncA, /* 线程入口函数 */
(void *)this, /* 线程入口函数的传入参数。这里传入的是我的窗口类对象“CMFCApplication1Dlg *const this” */
CREATE_SUSPENDED, /* 标记,CREATE_SUSPENDED标识创建的线程在创建后暂停。如果为0,创建时马上运行 */
&dwThreadIdA); /* 线程ID */
SetThreadPriority(hThreadA, THREAD_PRIORITY_ABOVE_NORMAL);标识创建的线程具有的优先级别//
创建线程B//
hThreadB = CreateThread(NULL,/* 使用默认的安全属性 */
100, /* 线程堆栈控件的大小 */
ThreadFuncB, /* 线程入口函数 */
(void *)this, /* 线程入口函数的传入参数。这里传入的是我的窗口类对象“CMFCApplication1Dlg *const this” */
0, /* 标记,CREATE_SUSPENDED标识创建的线程在创建后暂停。如果为0,创建时马上运行 */
&dwThreadIdB); /* 线程ID */
SetThreadPriority(hThreadB, THREAD_PRIORITY_ABOVE_NORMAL);标识创建的线程具有的优先级别//
创建一个手动重置(manual-reset events),未受信的(nonsignaled)事件//
g_hEvent = ::CreateEvent(NULL, TRUE, FALSE, EventObjName);
::ResetEvent(g_hEvent);//令事件为未受信的(nonsignaled)状态//
- 同时,添加线程处理函数
DWORD CMFCApplication1Dlg::ThreadFuncA(LPVOID pParam)
{
g_hEvent = OpenEvent(EVENT_ALL_ACCESS, NULL, EventObjName);
// 令事件为“置信”
::SetEvent(g_hEvent);
return EXIT_SUCCESS;
}
DWORD CMFCApplication1Dlg::ThreadFuncB(LPVOID pParam)
{
g_hEvent = OpenEvent(EVENT_ALL_ACCESS, NULL, EventObjName);
// 等待事件被“置信”,一直等待。下面这个等待语句前,一定要慎用Sleep函数。
// Sleep(10);// 不用Sleep函数来等待了,下面函数就有等待功能。
WaitForSingleObject(g_hEvent, INFINITE);
AfxMessageBox("大家好,我叫线程B。谢谢线程A把我叫醒!");
return EXIT_SUCCESS;
}
- 退出程序时,释放事件内核对象占用的空间
在MFCApplication1.cpp文件中,将事件内核对象的句柄声明为外部定义了的变量,用extern关键字
extern HANDLE g_hEvent;//事件内核对象的句柄
然后,在程序实例退出的地方,添加关闭句柄的语句:
else if (nResponse == IDCANCEL)
{
// TODO: 在此放置处理何时用
// “取消”来关闭对话框的代码
CloseHandle(g_hEvent);
}
- 运行效果:
有疑问可以留言哦。
放上代码链接:
MFC两个线程中用事件内核对象通信
https://download.csdn.net/download/u012210613/11046606