线程间的通信
1 方式1
int g_Num = 100;
UINT __cdecl ThreadWriteProc(LPVOID lpParameter)
{
while(TRUE) {
++g_Num; // 该线程对全局变量进行修改
Sleep(50);
}
return 100;
}
UINT __cdecl ThreadReadProc(LPVOID lpParameter)
{
CString strTipMsg;
while(TRUE) {
strTipMsg.Format(_T("%d"), g_Num);
OutputDebugString(strTipMsg); // 该线程对全局变量进行读取
Sleep(50);
}
return 100;
}
void CThreadTestDlg::OnBnClickedBtn()
{
CWinThread *pThread = AfxBeginThread(ThreadWriteProc, NULL); //按钮的回调函数中创建2个线程
AfxBeginThread(ThreadReadProc, NULL);
}
- 如何创建在多个源文件中都可以使用的全局变量? 三个步骤
1.先在某一个源文件中创建一个全局变量如:int g_Num = 100;
2.在另一个头文件中声明extern int g_Num;
3.在其他的需要使用该全局变量的源文件中包含第2步中的头文件即可
2 方式2
- 所有的线程都可以访问的某个东东可以用于线程之间的信息传递
如共同都能访问到的某个类的成员
3 方式3
- 发消息的方式 PostThreadMessage()
// 例如线程A给线程B发送消息,数据的传送通过消息的参数参数传递
#define MY_THREAD_MSG (WM_USER+100)
//自定义消息(这里的知识不是很清晰,需要学习一下,先了解框架)
UINT __cdecl ThreadWriteProc(LPVOID lpParameter)
{
int nCount = 0;
DWORD dwThreadReadID = (DWORD)lpParameter; // 获取到发消息的目标线程的ID
while(TRUE) {
PostThreadMessage(dwThreadReadID, MY_THREAD_MSG, nCount++, NULL); // 发送消息给目标线程,其中含有参数
Sleep(50);
}
return 0;
}
UINT __cdecl ThreadPrintProc(LPVOID lpParameter)
{
MSG msg = {0};
while(GetMessage(&msg, 0, 0, 0)) // 获取消息
{
switch(msg.message) { // 判断消息类型
case MY_THREAD_MSG:
{
int nCount = (int)msg.wParam;
CString strText;
strText.Format(_T("%d"), nCount);
OutputDebugString(strText); // 打印
}
break;
}
}
return 0;
}
void CThreadTestDlg::OnBnClickedBtn()
{
//启动打印线程
CWinThread *pThreadPrint = AfxBeginThread(ThreadPrintProc, NULL);
//启动写数据线程
//线程传递参数为,消息目的线程的ID
CWinThread *pThreadWrite = AfxBeginThread(ThreadWriteProc, (LPVOID)pThreadPrint->m_nThreadID);
}
4 MFC中程序主线程和新创建的界面线程之间的通信
(1)
// 在主线程中进行创建界面线程时调用AfxBeginThread()返回的CWinThread指针,就是新界面线程的指针
// 将CWinThread指针转换成新界面线程的指针,也就获取到了新界面线程的指针,就可以对新界面线程进行操作
// 比如修改或者赋值新界面线程中的值,以达到实现通信的目的
(2)
// 在新的界面线程中又该怎么向主线程进行通信呢?-------类似的方法
// 在新界面线程中调用AfxGetApp(),获取到程序的主线程的指针
// 于是进行强制转换之后可以对主线程的某些属性和方法进行访问和读写
(3)
// 发消息的方式也可以用于实现界面线程之间的同信,甚至还简单一些,因为界面线程自带消息循环,所以不需要像工作线程一样必须写消息循环,然后处理消息
// 这里所做的应该是重载界面线程类中的PreTranslateMessage方法.以使界面线程可以识别我自定义的消息