20170710Windows11_2_事件内核对象

内核对象——事件内核对象:

事件内核对象(1)

1:线程的同步:
#include <cstdio>
#include <tchar.h>
#include <windows.h>
#include <process.h>

int *g_pNum = nullptr;
bool g_Using = false;

void Entry()//原子操作,进入锁
{
	while (InterlockedExchange((long*)&g_Using, true) == true)
	{
		Sleep(0);
	}
}

void Leave()//原子操作,离开锁。
{
	InterlockedExchange((long*)&g_Using, false);
}

void ThreadPrintf(TCHAR* strText)
{
	Entry();
	_tprintf(strText);//非线程安全的,需要加锁。
	Leave();
}

unsigned __stdcall StartThread(void* lParam)
{
	ThreadPrintf(TEXT("Enter StartThread\r\n"));
	g_pNum = new int(0);
	Sleep(1000);
	ThreadPrintf(TEXT("End StartThread\r\n"));
	return 0;
}

unsigned __stdcall EndThread(void* lParam)
{
	ThreadPrintf(TEXT("Enter EndThread\r\n"));
	HANDLE hStart = lParam;
	ThreadPrintf(TEXT("Waiting EndThread\r\n"));
	WaitForSingleObject(hStart, INFINITE); //会使EndThread处于不可调度,节约资源。
	delete g_pNum;
	ThreadPrintf(TEXT("End EndThread\r\n"));
	return 0;
}

int main()
{
	HANDLE hStart = (HANDLE)_beginthreadex(nullptr, 0, StartThread, nullptr, 0, nullptr);
//	Sleep(1000);//用于控制先后顺序
	HANDLE hEnd = (HANDLE)_beginthreadex(nullptr, 0, EndThread, hStart, 0, nullptr);
	WaitForSingleObject(hEnd, INFINITE);

	return 0;
}

2:事件内核对象也是一种用于线程进程同步的内核对象,它可以自动重置也可以手动重置。最为重要的参数是Signal参数,事件内核对象创建的时候可以使用那个CreateEvent。 创建事件内核对象的时候,会设置重置的方式,FALSE为自动重置,TRUE为手动重置。

事件内核对象(2)——自动及手动及信号及No信号:

1:很显然,Thread和Process的内核对象并不是专门拿来做同步的,只是里面有Signal这个成员了,可以对此进行Wait的操作,事件内核对象是一个较为特殊的内核对象,他并非一个实体,里面也有使用计数,Signal状态,我们可以自动或者手动设置状态。
2:使用CreateEvent,CreateEventEx(XP下无法使用)。
CreateEventW(
    _In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes,	//安全指针,一般传nullptr
    _In_ BOOL bManualReset,	//是否为人为置位。
    _In_ BOOL bInitialState,	//初始化状态。TRUER为有信号状态
    _In_opt_ LPCWSTR lpName	//事件内核对象名称。
    );


3:其他进程仅能通过事件内核对象的名称来访问这个事件内核对象,如果事件内核对象内有设置名称就为匿名事件内核对象,这样的内核对象只能在当前进程里面使用。
#include <windows.h>

int main()
{
	HANDLE hEvent = CreateEvent(nullptr, TRUE, TRUE, nullptr);//此事件内核对象只能在本进程里面使用
	WaitForSingleObject(hEvent, INFINITE);//会等待一个内核对象变为Signal状态。
	ResetEvent(hEvent);// 会使这个内核对象变为no Signal状态。
	WaitForSingleObject(hEvent, INFINITE);//手动重置,不Reset就会直接通过,Reset就会阻塞在这里
	//如果为自动重置,那么WaitForSingleObject就会改变内核对象里面的Signal状态,下一次WaitForSingleObject就会阻塞。
	CloseHandle(hEvent);
	return 0;
}

4:自动重置状态会导致WaitForSingleObject会改变事件内核对象里面的Signal状态,如果为手动重置,那么在不掉用ResetEvent的情况下,内核对象会一直处于有信号状态,WaitForSingleObject也不可以改变其Signal状态。

事件内核对象(3)——作业:

1:CreateEventEx:参数含义与CreateEvent有所不同。
CreateEventExW(
    _In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes,	//权限访问符
    _In_opt_ LPCWSTR lpName,	//内核对象名称
    _In_ DWORD dwFlags,		//CREATE_EVENT_INITIAL_SET或者CREATE_EVENT_MANUAL_RESET。代表有信号状态,手动的。不传递这个参数,就为noSignal的自动的。
    _In_ DWORD dwDesiredAccess	//权限设置。
    );

2:CreateEvent是默认全权限的,可以做任何事情,而CreateEventEx可以设置里面的权限。主要用于设置对Event操作的权限。也有读权限,写权限等:
    读权限:只能来WaitForSignalObject,写权限:可以Set和Reset内核对象。SetEvent可以使之变为有信号状态,ResetEvent可以使之变为无信号状态。

事件内核对象(4)——练习:

1:我们在word里面编辑的时候,会发现其有字数统计(会有延后),拼写检查等等,输入网址他会自动设置为连接(渲染),事实上,他是使用的多线程来实现的。
void CEventDemoDlg::OnSetfocusEditText()
{
	// TODO:  在此添加控件通知处理程序代码
	if (m_hThreadGetCount == INVALID_HANDLE_VALUE)
	{
		m_hThreadGetCount = (HANDLE)_beginthreadex(nullptr, 0, ThreadGetCount, this, 0, nullptr);
	}
	if (m_hIsUrl == INVALID_HANDLE_VALUE)
	{
		m_hIsUrl = (HANDLE)_beginthreadex(nullptr, 0, ThreadIsUrl, this, 0, nullptr);
	}
	SINGLE_LIST_ENTRY hEventSignal;
	SetEvent(m_hEvent);//Event变为有信号
}

void CEventDemoDlg::OnKillfocusEditText()
{
	// TODO:  在此添加控件通知处理程序代码
	ResetEvent(m_hEvent);//无信号3
}


unsigned __stdcall CEventDemoDlg::ThreadGetCount(void* lParam)
{
	CEventDemoDlg* pThis = (CEventDemoDlg*)lParam;
	static CString strText;
	size_t nCount = 0;
	while (TRUE)
	{
		WaitForSingleObject(pThis->m_hEvent, INFINITE);
		pThis->GetDlgItemText(IDC_EDIT_TEXT, strText);
		nCount = strText.GetLength();
		pThis->SetDlgItemInt(IDC_STATIC_COUNT, nCount);
		Sleep(50);
	}
	return 0;
}

unsigned __stdcall CEventDemoDlg::ThreadIsUrl(void* lParam)
{
	CEventDemoDlg* pThis = (CEventDemoDlg*)lParam;
	WaitForSingleObject(pThis->m_hEvent, INFINITE);
	return 0;
}

2:上面是使用事件内核对象和多线程统计字数的一个例子。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值