MFC(2)MFC中使用信号量(semaphore)做线程同步——用户启动子线程打开串口

新建基于对话框的MFC工程,OpenDevice这个类由DLG类调用。(我的平台是:Win7-x64 / VisualStudio 2012 Ultimate)


OpenDevice.h

<span style="font-size:18px;">#pragma once
class OpenDevice
{
public:
	OpenDevice(void);
	~OpenDevice(void);

public:
	CWinThread *m_pThread;

	HANDLE	m_hCom;
	HANDLE	m_hSemaphore;
	BOOL SemIncrease(void);

	BOOL Init(void);
	BOOL OpenSerial(void);
	static UINT work_thread(void *args);
};
</span>

OpenDevice.c

<span style="font-size:18px;">#include "stdafx.h"
#include "OpenDevice.h"


OpenDevice::OpenDevice(void)
{
	m_hCom = NULL;
	m_hSemaphore = NULL;
	m_pThread = NULL;
}


OpenDevice::~OpenDevice(void)
{
	if(NULL != m_hCom)
	{
		CloseHandle(m_hCom);
		m_hCom = NULL;
	}

	if(NULL != m_hSemaphore)
	{
		CloseHandle(m_hSemaphore);
		m_hSemaphore = NULL;
	}
}

//初始化信号量,创建子线程(创建的时候立即运行)
BOOL OpenDevice::Init(void)
{
	//创建并初始化信号量
	m_hSemaphore = CreateSemaphore(NULL, 0, 1, NULL);
	if(NULL == m_hSemaphore)
	{
		TRACE(strerror(GetLastError()));
		return FALSE;
	}

	//创建子线程
	m_pThread = AfxBeginThread(work_thread, this);
	if(NULL == m_pThread)
	{
		TRACE(strerror(GetLastError()));
		return FALSE;
	}

	return TRUE;
}

BOOL OpenDevice::OpenSerial(void)
{
	if(NULL == m_hSemaphore)
	{
		return FALSE;
	}

	//等待串口设备插入:当用户点击打开按钮时,增加信号量的值,则WaitForSingleObject返回
	//并且减少一个值;然后去打开设备文件,失败后则重新阻塞等待信号量有效。
	while(1)
	{
		TRACE("wait for semaphore...\n");

		DWORD res = WaitForSingleObject(m_hSemaphore, INFINITE);				//wait 相当于 信号量的P操作
		if(WAIT_OBJECT_0 != res)
		{
			TRACE(strerror(GetLastError()));
			continue;
		}

		//打开串口文件
		m_hCom = CreateFile(	"COM3",
								GENERIC_WRITE | GENERIC_READ,
								0,
								NULL,
								OPEN_EXISTING,
								FILE_FLAG_OVERLAPPED,
								0);
		if(INVALID_HANDLE_VALUE == m_hCom)
		{
			TRACE(strerror(GetLastError()));
			AfxMessageBox("串口打开失败!");
		}
		else
		{
			TRACE("open successful\n");
			return TRUE;
		}								
	}
}

UINT OpenDevice::work_thread(void *args)
{
	OpenDevice *pOpenDevice = (OpenDevice *)args;
	BOOL res = pOpenDevice->OpenSerial();
	if(TRUE == res)
	{
		while(1)
		{
			TRACE("read and write serial!\n");
			Sleep(5000);
		}
	}

	return 0;
}

//信号量的V操作
BOOL OpenDevice::SemIncrease(void)
{
	if(NULL == m_hSemaphore)
	{
		return FALSE;
	}

	BOOL res = ReleaseSemaphore(m_hSemaphore, 1, NULL);
	if(0 == res)
	{
		TRACE(strerror(GetLastError()));
		return FALSE;
	}

	return TRUE;
}</span>


按钮响应函数:

void CsemaphoreDlg::OnBnClickedOpen()
{
	// TODO: 在此添加控件通知处理程序代码
	m_openDevice.SemIncrease();

}



MFC中信号量的操作和linux中的信号量操作基本相同,只是linux中单独有函数做PV操作。

下面是一个使用Semaphore实现两线程同步的C++代码: ```c++ #include <iostream> #include <thread> #include <mutex> #include <condition_variable> #include <semaphore.h> using namespace std; sem_t sem; void thread1() { cout << "Thread 1 is running." << endl; sem_post(&sem); // 发送信号量 } void thread2() { sem_wait(&sem); // 等待信号量 cout << "Thread 2 is running." << endl; } int main() { sem_init(&sem, 0, 0); // 初始化信号量 thread t1(thread1); thread t2(thread2); t1.join(); t2.join(); sem_destroy(&sem); // 销毁信号量 return 0; } ``` 这个例子,我们使用了`sem_t`和`sem_init()`、`sem_wait()`、`sem_post()`、`sem_destroy()`四个函数来实现Semaphore。`sem_t`是一个结构体类型,用于存储Semaphore的信息。`sem_init()`函数用于初始化Semaphore,第一个参数是Semaphore结构体指针,第二个参数是0表示这个Semaphore是用于线程间同步的,第三个参数是Semaphore的初值,这里设为0。`sem_wait()`函数用于等待Semaphore的信号,如果Semaphore的值为0,则该函数阻塞线程,直到Semaphore的值大于0;如果Semaphore的值大于0,则该函数将Semaphore的值减1,然后线程继续执行。`sem_post()`函数用于发送Semaphore的信号,将Semaphore的值加1,表示Semaphore可以被下一个等待的线程使用。`sem_destroy()`函数用于销毁Semaphore。 在这个例子,我们创建了两个线程线程1通过调用`sem_post()`函数发送Semaphore的信号,线程2通过调用`sem_wait()`函数等待Semaphore的信号。由于Semaphore的初值为0,线程2会在等待Semaphore的信号时被阻塞,直到线程1发送了Semaphore的信号。这样就实现了两个线程的同步。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值