欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

线程间通信

程序员文章站 2022-06-10 20:50:03
...

线程间通信

全局变量或类的成员变量

1. 全局变量

定义一个全局变量,开启两个线程一个进行自减,一个进行打印,并使用CCriticalSection类’临界区’进行线程同步。

//CSyncThreadDlg.h
UINT ThreadPoc3(LPVOID pParam);//全局变量 线程函数
UINT ThreadPoc4(LPVOID pParam);
extern UINT g_Num;

public:
CCriticalSection m_cs;//临界区对象


CSyncThreadDlg.h
UINT g_Num = 1000;
void CSyncThreadDlg::OnBnClickedButtonCreateGlobal()
{
	CString str;
	GetDlgItem(IDC_BUTTON_CREATE_GLOBAL)->GetWindowText(str);
	if (_T("创建线程") == str)
	{
		GetDlgItem(IDC_BUTTON_CREATE_GLOBAL)->SetWindowText(_T("退出线程"));
		pGloBalThread3 = AfxBeginThread(ThreadPoc3, NULL);
		pGloBalThread4 = AfxBeginThread(ThreadPoc4, this);
		//更新UI界面
		GetDlgItem(IDC_BUTTON_SUSPEND)->EnableWindow(TRUE);
	}
	else
	{
		GetDlgItem(IDC_BUTTON_CREATE_GLOBAL)->SetWindowText(_T("创建线程"));
		::TerminateThread(pGloBalThread3->m_hThread, 0);
		::TerminateThread(pGloBalThread4->m_hThread, 0);
	}
}

UINT ThreadPoc3(LPVOID pParam)
{
	while (TRUE)
	{
		g_Num--;
		Sleep(500);
	}
	return 0;
}

UINT ThreadPoc4(LPVOID pParam)
{
	CSyncThreadDlg *pDlg = (CSyncThreadDlg *)pParam;
	CString str;
	while (TRUE)
	{
		pDlg->m_cs.Lock();//加锁
		str.Format(_T("%d "), g_Num);
		pDlg->GetDlgItem(IDC_EDIT_GLOBAL)->SetWindowText(str);
		pDlg->m_cs.Unlock();//解锁
		OutputDebugString(str);
		Sleep(500);
	}
	return 0;
}

void CSyncThreadDlg::OnBnClickedButtonSuspend()
{
	CString str;
	GetDlgItem(IDC_BUTTON_SUSPEND)->GetWindowText(str);
	if (_T("挂起") == str)
	{
		GetDlgItem(IDC_BUTTON_SUSPEND)->SetWindowText(_T("唤醒"));
		SuspendThread(pGloBalThread3->m_hThread);//挂起线程
		SuspendThread(pGloBalThread4->m_hThread);
	}
	else
	{
		GetDlgItem(IDC_BUTTON_SUSPEND)->SetWindowText(_T("挂起"));
		ResumeThread(pGloBalThread3->m_hThread);//唤醒线程
		ResumeThread(pGloBalThread4->m_hThread);
	}
}
2. 类的成员变量

定义一个类的成员函数,开启两个线程一个进行自增,一个进行打印

//创建线程与退出线程
void CSyncThreadDlg::OnBnClickedButtonClassCreate()
{
	CString str;
	GetDlgItem(IDC_BUTTON_CLASS_CREATE)->GetWindowText(str);
	if (_T("创建线程") == str)
	{
		GetDlgItem(IDC_BUTTON_CLASS_CREATE)->SetWindowText(_T("退出线程"));
		pClassThread1 = AfxBeginThread(ThreadPoc1, this);
		pClassThread2 = AfxBeginThread(ThreadPoc2, this);
		m_Num = 0;
		//更新UI界面
		GetDlgItem(IDC_BUTTON_CLASS_SUPEND)->EnableWindow(TRUE);
	}
	else
	{
		GetDlgItem(IDC_BUTTON_CLASS_CREATE)->SetWindowText(_T("创建线程"));
		//TerminateThread以异步方式执行,函数返回不代表线程结束,
		//线程函数停止执行,位置随机,类对象不会被析构导致内存泄漏
		::TerminateThread(pClassThread1->m_hThread, 0);
		::TerminateThread(pClassThread2->m_hThread, 0);
	}	
}

UINT CSyncThreadDlg::ThreadPoc1(LPVOID pParam)
{
	CSyncThreadDlg *pDlg = (CSyncThreadDlg *)pParam;
	while (TRUE)
	{
		++(pDlg->m_Num);
		Sleep(500);
	}
	return 0;
}

UINT CSyncThreadDlg::ThreadPoc2(LPVOID pParam)
{
	CSyncThreadDlg *pDlg = (CSyncThreadDlg *)pParam;
	CString str;
	while (TRUE)
	{
		pDlg->m_cs.Lock();//加锁
		str.Format(_T("%d "), pDlg->m_Num);
		pDlg->GetDlgItem(IDC_EDIT_CLASS)->SetWindowText(str);
		pDlg->m_cs.Unlock();//解锁
		OutputDebugString(str);
		Sleep(500);
	}
	return 0;
}


void CSyncThreadDlg::OnBnClickedButtonClassSupend()
{
	CString str;
	GetDlgItem(IDC_BUTTON_CLASS_SUPEND)->GetWindowText(str);
	if (_T("挂起") == str)
	{
		GetDlgItem(IDC_BUTTON_CLASS_SUPEND)->SetWindowText(_T("唤醒"));
		SuspendThread(pClassThread1->m_hThread);//挂起线程
		SuspendThread(pClassThread2->m_hThread);
	}
	else
	{
		GetDlgItem(IDC_BUTTON_CLASS_SUPEND)->SetWindowText(_T("挂起"));
		ResumeThread(pClassThread1->m_hThread);//唤醒线程
		ResumeThread(pClassThread2->m_hThread);
	}
}

发消息方式

该方式需要自定义消息和绑定,然后一个线程进行消息的发送,而另一个线程不停的接收自定义的的消息,一接收到立马执行。

//方式三:使用创建发消息的方式进行通信
void CSyncThreadDlg::OnBnClickedButtonSendMsgCreate()
{
	CWinThread *pThreadPrint = AfxBeginThread(ThreadPrintProc, this);//输出打印线程
	CWinThread *pThreadWrite = AfxBeginThread(ThreadWriteProc, (LPVOID)pThreadPrint->m_nThreadID);
}

#define MY_THREAD_MSG (WM_USER+100) //自定义的消息

UINT CSyncThreadDlg::ThreadWriteProc(LPVOID pParam)
{
	UINT nCount = 0;
	DWORD dwThreadReadID = (DWORD)pParam;//线程ID号
	while (true)
	{
		//线程ID号  自动消息ID  消息参数
		PostThreadMessage(dwThreadReadID, MY_THREAD_MSG, nCount++, NULL);
		Sleep(500);
	}
	return 0;
}
//接收消息线程
UINT CSyncThreadDlg::ThreadPrintProc(LPVOID pParam)
{
	CSyncThreadDlg *pDlg = (CSyncThreadDlg*)pParam;

	MSG msg = { 0 };
	while (GetMessage(&msg,0,0,0))
	{
		switch (msg.message)
		{
		case MY_THREAD_MSG:
			{
				pDlg->m_cs.Lock();//加锁
				UINT nCount = (int)msg.wParam;
				CString str;
				str.Format(_T("%d "), nCount);
				pDlg->GetDlgItem(IDC_EDIT_SENDMESSAGE)->SetWindowText(str);
				pDlg->m_cs.Unlock();//解锁
				OutputDebugString(str);
				Sleep(500);
			}
			break;
		default:
			break;
		}
	}
	return 0;
}