关于事件
事件(Event)是WIN32提供的最灵活的线程间同步方式,事件可以处于激发状态(signaled or true)或未激发状态(unsignal or false)。根据状态变迁方式的不同,事件可分为两类:
(1)手动设置:这种对象只可能用程序手动设置,在需要该事件或者事件发生时,采用SetEvent及ResetEvent来进行设置。
(2)自动恢复:一旦事件发生并被处理后,自动恢复到没有事件状态,不需要再次设置。
创建事件的函数原型为:
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,
// SECURITY_ATTRIBUTES结构指针,可为NULL
BOOL bManualReset,
// 手动/自动
// TRUE:在WaitForSingleObject后必须手动调用ResetEvent清除信号
// FALSE:在WaitForSingleObject后,系统自动清除事件信号
BOOL bInitialState, //初始状态
LPCTSTR lpName //事件的名称
);
使用"事件"机制应注意以下事项:
(1)如果跨进程访问事件,必须对事件命名,在对事件命名的时候,要注意不要与系统命名空间中的其它全局命名对象冲突;
(2)事件是否要自动恢复;
(3)事件的初始状态设置。
看下面代码:
DWORD WINAPI ThreadProc(LPVOID lpParam);
DWORD WINAPI ThreadProc2(LPVOID lpParam);
DWORD g_dwThreadID;
DWORD g_dwThreadID2;
UINT g_nTickets = 300; //int g_nTickets = 300; //备注1
HANDLE g_hEvent = NULL;
HANDLE g_hEvent1 = NULL;
HANDLE g_hEvent2 = NULL;
CRITICAL_SECTION g_cs;
int ThreadCout = 0;
int main()
{
cout << "Main thread is running." << endl;
InitializeCriticalSection(&g_cs);//初始化临界区
HANDLE hHandle = CreateThread(NULL, 0, ThreadProc, NULL, 0, &g_dwThreadID);
ThreadCout++;
HANDLE hHandle2 = CreateThread(NULL, 0, ThreadProc2, NULL, 0, &g_dwThreadID2);
ThreadCout++;
//g_hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
g_hEvent1 = CreateEvent(NULL, FALSE, TRUE, NULL); //备注5:g_hEvent1 = CreateEvent(NULL, TRUE, TRUE, NULL);
g_hEvent2 = CreateEvent(NULL, FALSE, TRUE, NULL); //备注5:g_hEvent2 = CreateEvent(NULL, TRUE, TRUE, NULL);
ResetEvent(g_hEvent1);
ResetEvent(g_hEvent2);
SetEvent(g_hEvent1);
while (TRUE)
{
EnterCriticalSection(&g_cs);
int nCount = ThreadCout;
LeaveCriticalSection(&g_cs);
if (nCount == 0)
{
cout << "Main thread is break." << endl;
break;
}
}
Sleep(1000); //备注4
CloseHandle(hHandle);
CloseHandle(hHandle2);
DeleteCriticalSection(&g_cs);
cout << "Main thread is end." << endl;
system("pause");
return 0;
}
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
// cout << "No." << g_dwThreadID << " thread is running." << endl;
while (TRUE)
{
WaitForSingleObject(g_hEvent1, INFINITE);
cout << "No.1 " << g_dwThreadID << " thread is running." << endl;
EnterCriticalSection(&g_cs);
int temp= g_nTickets;
LeaveCriticalSection(&g_cs);
cout << "No.1 " << g_dwThreadID << " thread is temp." << endl;
if (temp > 0)
{
Sleep(10); //Sleep(1000) //备注2
cout << "No.1-" << g_dwThreadID << " sell ticket : " << temp << endl;
EnterCriticalSection(&g_cs);
g_nTickets--;
LeaveCriticalSection(&g_cs);
SetEvent(g_hEvent2);
//ResetEvent(g_hEvent1);//备注6
}
else
{
cout << "No.1- break" << endl;
//ResetEvent(g_hEvent1);//备注6
SetEvent(g_hEvent2);//没有这个ThreadProc2不能终止 //备注3
break;
}
}
EnterCriticalSection(&g_cs);
ThreadCout--;
LeaveCriticalSection(&g_cs);
cout << "No.1- end" << endl;
return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lpParam)
{
//
while (TRUE)
{
WaitForSingleObject(g_hEvent2, INFINITE);
cout << "No.2 " << g_dwThreadID2 << " thread is running." << endl;
EnterCriticalSection(&g_cs);
int temp= g_nTickets;
LeaveCriticalSection(&g_cs);
if (temp > 0)
{
Sleep(10); //Sleep(1000) //备注2
cout << "No.2-" << g_dwThreadID2 << " sell ticket : " << temp << endl;
EnterCriticalSection(&g_cs);
g_nTickets--;
LeaveCriticalSection(&g_cs);
SetEvent(g_hEvent1);
//ResetEvent(g_hEvent2);//备注6
}
else
{
cout << "No.2- break" << endl;
//ResetEvent(g_hEvent2);//备注6
SetEvent(g_hEvent1);//同样的问题,没有这个ThreadProc不能终止 //备注3
break;
}
}
EnterCriticalSection(&g_cs);
ThreadCout--;
LeaveCriticalSection(&g_cs);
cout << "No.2- end" << endl;
return 0;
}
这个代码是接上一遍关于UINT类型作为循环变量的不确定性问题继续完善的,加入了临界区控制全局变量的访问。
本文要说明的是SetEvent和ResetEvent的使用,这个要看备注5和备注6。
备注5处:
CreateEvent的第二个参数决定了是否需要手动调用ResetEvent,当为TRUE时,是需要手动调用,如果不调用,会怎么样呢?不调用,事件会处于一直有信号状态,即备注6处。当为FALSE时候,不需要手动调用,调用不调用,效果一样。
分享到:
相关推荐
同一事件变量,调用WaitForSingleObject在不同函数中返回结果不同.
线程中CreateEvent和SetEvent及WaitForSingleObject的用法
事件的使用实例。主要示例了CreateEvent、SetEvent、ResetEvent、WaitForSingleObject函数的使用。
临界区的互斥控制_SetEvent置句柄为有信号状态配合WaitForSingleObject使用_INFINITE等待其运行结束
sendmessage, CreateEvent, setEvent,进程通信,通过CreateEvent和setEvent来实现,sendmessage发送消息
测试WaitForSingleObject,CreateEvent SetEvent,vs2008实现
采用timeSetEvent定时器来计算数据,使用OnTimer定时器来显示图形;数据计算误差不超过1ms。先将图形绘制到内存中,然后显示,不会闪烁不清。面板可以动态设置参数调整波形
界面开发所用到的主要控件,包括命令按钮,组合框,进度条及菜单等.
代码中包含了UDP通信的基本编程发放,实现消息的发送和接收。程序采用回调函数接收对方发来的UDP数据,并通过字符串的形式显示在接收窗口的便捷框中。UDP通信被封装成了类,方便初学者学习使用。c++代码实现。函数...
CreateEvent() 在内核中创建一个新的事件对象。此函数允许有安全性设置、手工还是自动重置的标志以及初始时已接受还是未接受信号状态的标志 OpenEvent() 创建对已经存在的事件对象的引用。此API函数需要名称、继承...
易语言线程池类模块源码,线程池类模块,启动线程池,提交任务,关闭线程池,线程,call,CreateIoCompletionPort,GetQueuedCompletionStatus,PostQueuedCompletionStatus,CreateThread,CloseHandle,SetEvent,...
window.event对象详解。event对象只在事件发生的过程中才有效;event的某些属性只对特定的事件有意义。比如,fromElement 和 toElement 属性只对 onmouseover 和 onmouseout 事件有意义。
这种同步方法通常可以用在post中,拨号前先同步可能避免数据没有返回就启动了拨号。需要调用到四个windows API函数。CreateEvent。ResetEvent 。SetEvent 。WaitForSingleObject。@付笑。
本实例代码适合对事件触发机制的认识、使用上可提升代码质量,工程代码可以直接拷贝到项目中使用。
易语言读写锁源码,读写锁,分配读写锁,释放,创建,销毁,读进入,读退出,写进入,写退出,原子锁_必进,读线程回调,写线程回调,创建线程,CreateEventA,WaitForSingleObject,ResetEvent,SetEvent,CreateThread,CloseHandle,...
这种同步方法通常可以用在post中,拨号前先同步可能避免数据没有返回就启动了拨号 需要调用到四个windows API函数 CreateEvent ResetEvent SetEvent WaitForSingleObject
这种同步方法通常可以用在post中,拨号前先同步可能避免数据没有返回就启动了拨号 需要调用到四个windows API函数 CreateEvent ResetEvent SetEvent WaitForSingleObject 效果图
2009-02-07:将u_cst_toolbarstripbutton增加实例变量is_event,并增加函数of_setevent(string as_event):is_event=as_event 20090218:在u_cst_tabstrip中增加变量ib_allowClose,用以控制当前tab是否允许关闭(比如...
SetEvent SetPriorityClass SetThreadPriority Sleep SuspendThread TerminateProcess TerminateThread TlsAlloc TlsFree TlsGetValue TlsSetValue WaitForInputIdle ...