详细介绍: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

如链接示例中

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 函数

BOOL PostMessageA(
  [in, optional] HWND   hWnd,
  [in]           UINT   Msg,
  [in]           WPARAM wParam,
  [in]           LPARAM lParam
);

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

价值意义

HWND_BROADCAST

((HWND)0xffff)

该消息将发布到系统中的所有顶级窗口,包括已禁用或不可见的未所有者窗口、重叠的窗口和弹出窗口。 消息不会发布到子窗口。

该函数的行为类似于调用 PostThreadMessagedwThreadId 参数设置为当前线程的标识符。

Msg:要发布的消息。

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

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

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


范例

UINT CalcPrime(LPVOID param);

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


程序优化

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

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

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

posted @ 2025-12-24 22:20  clnchanpin  阅读(28)  评论(0)    收藏  举报