MFC多线程学习笔记三:线程间的通信

使用全局变量进行通信

对于标准型的全局变量,建议使用volatile修饰符,告诉编译器无需优化(不放入寄存器),该值可以被外部改变。

如果线程间需要传递的信息比较复杂,可以使用结构,通过传递指向结构的指针来传递信息。

volatile修饰符

  1. 防止编译器优化

    声明为volatile的变量不会被编译器优化,每次访问都会直接读取内存值,避免因优化导致的数据不一致问题。 ‌12

  2. 保证内存可见性

    在多线程环境中,volatile变量的修改会立即同步到主内存,其他线程能读取到最新值,解决线程间数据不一致问题。 ‌34

  3. 禁止指令重排序

    通过插入内存屏障,防止编译器或处理器对volatile变量相关指令进行重排序,确保程序执行顺序符合预期。

https://blog.csdn.net/hd51cc/article/details/155131444?sharetype=blogdetail&sharerId=155131444&sharerefer=PC&sharesource=hd51cc&spm=1011.2480.3001.8118

如链接示例中

cpp 复制代码
volatile bool bExit1 = false;
volatile bool bExit2 = false;

...


void CMFCApplDlg::OnPriorityThread1()
{
	int prior;
	//线程存在
	if (m_pThread1 && !bExit1)
	{
		prior = m_pThread1->GetThreadPriority();
		if (prior == THREAD_PRIORITY_NORMAL )
		{
			m_pThread1->SetThreadPriority(THREAD_PRIORITY_ABOVE_NORMAL);
			AfxMessageBox(L"线程1的优先级提升1级", MB_OK);
		}
		else
		{
			m_pThread1->SetThreadPriority(THREAD_PRIORITY_NORMAL);
			AfxMessageBox(L"线程1的优先级降低1级", MB_OK);
		}
	}
}


void CMFCApplDlg::OnPriorityThread2()
{
	int prior;
	//线程存在
	if (m_pThread2 && !bExit2)
	{
		prior = m_pThread2->GetThreadPriority();
		if (prior == THREAD_PRIORITY_NORMAL)
		{
			m_pThread2->SetThreadPriority(THREAD_PRIORITY_ABOVE_NORMAL);
			AfxMessageBox(L"线程2的优先级提升1级", MB_OK);
		}
		else
		{
			m_pThread2->SetThreadPriority(THREAD_PRIORITY_NORMAL);
			AfxMessageBox(L"线程2的优先级降低1级", MB_OK);
		}
	}
}

....



void CMFCApplDlg::OnStopThread1()
{
	bExit1 = true;
	m_bEnable1 = true;
}


void CMFCApplDlg::OnStopThread2()
{
	bExit2 = true;
	m_bEnable2 = true;
}

使用自定义消息进行通信

步骤

1)定义一个自定义消息。

在头文件中自定义消息、声明消息处理函数。

在CPP文件中,映射消息,定义消息处理函数。

2)在一个函数中调用::PostMessage()向另一个线程发送自定义消息


PostMessageA 函数

cpp 复制代码
BOOL PostMessageA(
  [in, optional] HWND   hWnd,
  [in]           UINT   Msg,
  [in]           WPARAM wParam,
  [in]           LPARAM lParam
);

hWnd:窗口过程的句柄是接收消息。 以下值具有特殊含义。

价值 意义
HWND_BROADCAST ((HWND)0xffff) 该消息将发布到系统中的所有顶级窗口,包括已禁用或不可见的未所有者窗口、重叠的窗口和弹出窗口。 消息不会发布到子窗口。
该函数的行为类似于调用 PostThreadMessagedwThreadId 参数设置为当前线程的标识符。

Msg:要发布的消息。

wParam:其他特定于消息的信息。

lParam:其他特定于消息的信息。

返回值:如果函数成功,则返回值为非零。如果函数失败,则返回值为零。


范例

cpp 复制代码
UINT CalcPrime(LPVOID param);
cpp 复制代码
int n = 0;

UINT CalcPrime(LPVOID param)
{
	n = 0;
	long j, k;
	for (long i = 1; i <= 100000000; i += 2)
	{
		k = (long)sqrt(i);
		for (j = 2; j <= k; j++)
		{
			if (i % j == 0)
			{
				break;
			}
		}
		if (j >= k + 1)
		{
			n += 1;
		}
	}

	return 0;
}

程序优化

cpp 复制代码
const int WM_CALCULATE = WM_USER + 100;//自定义消息
...
afx_msg LONG OnThreadEnd(WPARAM aParam, LPARAM lParam);//消息处理函数

cpp 复制代码
BEGIN_MESSAGE_MAP(CMFCDlg, CDialogEx)
    ...
	ON_MESSAGE(WM_CALCULATE, OnThreadEnd)//自定义消息映射
END_MESSAGE_MAP()

LONG CMFCDlg::OnThreadEnd(WPARAM aParam, LPARAM lParam)
{
	CString s;
    s.Format(L"当前个数:%d .", n);
    AfxMessageBox(s);
	return 0;
}

void CMFCDlg::OnBnClickedPrime()
{
	HWND hWnd = GetSafeHwnd();//获取窗口句柄
	AfxBeginThread(CalcPrime, hWnd);

}



UINT CalcPrime(LPVOID param)
{
	n = 0;
	long j, k;
	for (long i = 1; i <= 10000000; i += 2)
	{
		k = (long)sqrt(i);
		for (j = 2; j <= k; j++)
		{
			if (i % j == 0)
			{
				break;
			}
		}
		if (j >= k + 1)
		{
			n += 1;
		}
	}
	::PostMessage((HWND)param, WM_CALCULATE, n, 0);//向主线程发送消息WM_CALCULATE
	return 0;
}

当计算结束,自动弹出对话框。这才是想要的结果

相关推荐
hd51cc1 小时前
MFC多线程学习笔记四:线程间的同步
笔记·学习·mfc
星空的资源小屋2 小时前
VNote:程序员必备Markdown笔记神器
javascript·人工智能·笔记·django
wdfk_prog2 小时前
[Linux]学习笔记系列 -- [block]bfq-iosched
linux·笔记·学习
摇滚侠2 小时前
Vue 项目实战《尚医通》,实名认证模块静态的搭建,笔记53
vue.js·笔记
embrace992 小时前
【C语言学习】结构体详解
android·c语言·开发语言·数据结构·学习·算法·青少年编程
FFF团团员9092 小时前
树莓派学习笔记4:终端常用指令
笔记·学习
L***一2 小时前
中专毕业生计算机证书选择指南:零基础入门路径(2026届适用)
学习
Radan小哥2 小时前
Docker学习笔记—day008
笔记·学习·docker
源代码•宸3 小时前
GoLang写一个简单版生命游戏模拟器
经验分享·笔记·学习·游戏·golang