Win32 事件

1.内核对象

1.什么是内核对象

前面我们知道了怎么判断是否为内核对象,即在创建对象时是否有LPSECURITY_ATTRIBUTES参数,起始我们创建的内核对象会给我们返还一个句柄,句柄就是内核对象的一个编号,因为操作系统不可能把真正的地址给我们,避免出现恶意破坏的风险

2.事件内核对象的创建

HANDLE g_hEvent = CreateEvent(NULL, TRUE, FALSE, "XYZ");

HANDLE g_hMutex = CreateMutex(NULL,FALSE, "XYZ");

3.内核对象的获取

以Open的方式我们可以跨进程获取对象

4.内核对象的销毁

 当内核对象被其他进程引用时,内核对象会被延长声生命周期

5.内核对象的生命周期

实验:CloseHandle()/进程结束							
							
进程一:							
							
HANDLE g_hEvent = CreateEvent(NULL, TRUE, FALSE, "XYZ");							
							
SetEvent(g_hEvent);							
							
							
进程二:							
							
HANDLE g_hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, "XYZ");							
							
WaitForSingleObject(g_hEvent, INFINITE);							
							
							
实验一:内核对象的生命周期							
							
进程一:							
							
HANDLE g_hEvent = CreateEvent(NULL, TRUE, FALSE, "XYZ");							
							
SetEvent(g_hEvent);							
							
							
进程二:							
							
HANDLE g_hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, "XYZ");							
							
WaitForSingleObject(g_hEvent, INFINITE);							
							
							

当进程1创建了内核对象后,不销毁,此时进程2进行引用的话对象的生命周期就会被延长

当进程1创建了内核对象后,销毁的话,此时进程2就无法进行引用,对象的生命周期结束

当进程1创建了内核对象后,不进行销毁,此时进程2进行引用,进程1再进行销毁时,对象的生命周期依然存在

2.事件对象

1.事件对象的创建

 第二个参数为TRUE时,表示需要手动将事件对象标记为未通知(即一直保持已通知状态),为FALSE时,表示WaitForSingleObject函数会自动将事件对象修改为未通知状态。

第三个参数为TRUE时,表示事件对象创建出来就是已通知状态,为FALSE时,表示创建出来就是未通知状态

2.事件状态的控制

BOOL SetEvent(HANDLE hEvent);   //可以实现将事件状态修改为已通知

BOOL ResetEvent(HANDLE hEvent);  //可以实现将事件状态修改为未通知

3.关闭事件对象的控制

CloseHandle();   //关闭句柄

4.线程控制实验:只读形式的线程控制

// xxxx.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include <windows.h>
#include "resource.h"

HWND hEdit1;
HWND hEdit2;
HWND hEdit3;
HWND hEdit4;

HANDLE hThread1;
HANDLE hThread2;
HANDLE hThread3;

HANDLE g_hEvent;

DWORD WINAPI ThreadProc1(LPVOID lpParameter)
{
		
	WaitForSingleObject(g_hEvent,-1);
	TCHAR buffer[10];
	memset(buffer,0,10);

	GetWindowText(hEdit1,buffer,10);

	SetWindowText(hEdit2,buffer);

	return 0;
}

DWORD WINAPI ThreadProc2(LPVOID lpParameter)
{	
	WaitForSingleObject(g_hEvent,-1);
	TCHAR buffer[10];
	memset(buffer,0,10);

	GetWindowText(hEdit1,buffer,10);

	SetWindowText(hEdit3,buffer);

	return 0;
}

DWORD WINAPI ThreadProc3(LPVOID lpParameter)
{	
	WaitForSingleObject(g_hEvent,-1);
	TCHAR buffer[10];
	memset(buffer,0,10);

	GetWindowText(hEdit1,buffer,10);

	SetWindowText(hEdit4,buffer);

	return 0;
}

DWORD WINAPI ThreadProc_Main(LPVOID lpParameter)
{
	g_hEvent=CreateEvent(NULL,true,false,NULL);

	hThread1=CreateThread(NULL,0,ThreadProc1,NULL,0,NULL);

	hThread2=CreateThread(NULL,0,ThreadProc2,NULL,0,NULL);

	hThread3=CreateThread(NULL,0,ThreadProc3,NULL,0,NULL);

	SetEvent(g_hEvent);
	
	CloseHandle(hThread1);

	CloseHandle(hThread2);

	CloseHandle(hThread3);

	CloseHandle(g_hEvent);
	return 0;
}


BOOL CALLBACK MainDlgProc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)					
{					
					
						
		switch(uMsg)				
		{				
		case WM_CLOSE:				
			{			
				EndDialog(hDlg,0);		
				break;		
			}			
		case WM_INITDIALOG:				
			{			
				hEdit1 = GetDlgItem(hDlg,IDC_EDIT1);		
				SetWindowText(hEdit1,"1000");
				
				hEdit2 = GetDlgItem(hDlg,IDC_EDIT2);		
				SetWindowText(hEdit2,"0");
				
				hEdit3 = GetDlgItem(hDlg,IDC_EDIT3);		
				SetWindowText(hEdit3,"0");
 
				hEdit4 = GetDlgItem(hDlg,IDC_EDIT4);		
				SetWindowText(hEdit4,"0");
				break;		
			}			
		case WM_COMMAND:				
			{		
				switch (LOWORD (wParam))			
				{			
				case IDC_BUTTON1:			
					{		
						HANDLE hThread_Main=CreateThread(NULL,0,ThreadProc_Main,NULL,0,NULL);

						CloseHandle(hThread_Main);
						return TRUE;	
					}		
					
				}			
						
						
			}		
			break;			
		}
		return FALSE;
}


int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
 	DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG_MAIN),NULL,MainDlgProc);	

	return 0;
}



注意:这里能够实现三个线程同时读取全局变量是因为在创建事件对象时,我们第二个参数是true,因此在使用的时候,如果我们不手动修改事件对象的状态的话,那么事件对象的状态就一直是已通知状态,那么其他线程就能Wait到

3.线程同步

什么是线程同步?

 线程同步是指在多线程编程中,为了保证多个线程按照某种特定的方式正确、有序地执行,需要进行线程间的协作与同步。在多线程编程中,当多个线程共享同一份资源时,由于线程的执行顺序是不确定的,因此会存在一些并发问题,如死锁、竞态条件、资源争用等问题。为了避免这些问题,需要对线程进行同步。线程同步实际上就是通过线程之间的协作,使得线程能够按照一定的顺序来访问共享资源,从而避免并发问题的发生。

参见:线程同步

事件对象实现线程同步


#include "stdafx.h"
#include <windows.h>
#include <stdio.h>

//事件和临界区		
HANDLE g_hSet, g_hClear;		
int g_Max = 10;		
int g_Number = 0;		
                   		
//生产者线程函数  		
DWORD WINAPI ThreadProduct(LPVOID pM)  		
{  		
    for (int i = 0; i < g_Max; i++)		
    {  		
        WaitForSingleObject(g_hSet, INFINITE);  		
		g_Number = 1; 
		DWORD id = GetCurrentThreadId();
		printf("生产者%d将数据%d放入缓冲区\n",id, g_Number); 
        SetEvent(g_hClear);   		
    }  		
    return 0;  		
}  		
//消费者线程函数		
DWORD WINAPI ThreadConsumer(LPVOID pM)  		
{  		
    for (int i = 0; i < g_Max; i++)		
    {  		
        WaitForSingleObject(g_hClear, INFINITE);  		
		g_Number = 0; 
		DWORD id = GetCurrentThreadId();
		printf("----消费者%d将数据%d放入缓冲区\n",id, g_Number); 
        SetEvent(g_hSet);   		
    }  		
    return 0;  		
}  		
		
int main(int argc, char* argv[])		
{		
		
    HANDLE hThread[2]; 		
		
	g_hSet = CreateEvent(NULL, FALSE, TRUE, NULL);  	
    g_hClear = CreateEvent(NULL, FALSE, FALSE, NULL); 		
		
    hThread[0] = ::CreateThread(NULL, 0, ThreadProduct, NULL, 0, NULL); 		
	hThread[1] = ::CreateThread(NULL, 0, ThreadConsumer, NULL, 0, NULL);	
		
    WaitForMultipleObjects(2, hThread, TRUE, INFINITE);  		
    CloseHandle(hThread[0]);  		
    CloseHandle(hThread[1]);		
		
	//销毁 	
	CloseHandle(g_hSet);  	
    CloseHandle(g_hClear);  		
		
	return 0;	
}		


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值