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;
}

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

相关推荐
孙严Pay1 天前
快捷支付:高效安全的在线支付新选择
笔记·科技·计算机网络·其他·微信
じ☆冷颜〃1 天前
黎曼几何驱动的算法与系统设计:理论、实践与跨领域应用
笔记·python·深度学习·网络协议·算法·机器学习
想进部的张同学1 天前
hilinux-3599---设备学习---以及部署yolo
学习·yolo·海思
HyperAI超神经1 天前
【vLLM 学习】Rlhf
人工智能·深度学习·学习·机器学习·vllm
数据皮皮侠AI1 天前
上市公司股票名称相似度(1990-2025)
大数据·人工智能·笔记·区块链·能源·1024程序员节
yuhaiqun19891 天前
学服务器训练AI模型:5步路径助力高效入门
运维·服务器·人工智能·笔记·机器学习·ai
雍凉明月夜1 天前
深度学习网络笔记Ⅳ(Transformer + VIT)
笔记·深度学习·transformer
做cv的小昊1 天前
【TJU】信息检索与分析课程笔记和练习(7)数据库检索—Ei
数据库·笔记·学习·全文检索
AI360labs_atyun1 天前
上海打出“开源”国际牌!2025重磅新政
人工智能·科技·学习·ai·开源
Chris_12191 天前
Halcon学习笔记-Day6:工业视觉高级技术应用与实战项目
笔记·学习·halcon