windows多线程同步之事件对象

来源:互联网 发布:c语言猜拳游戏代码 编辑:程序博客网 时间:2024/04/27 17:01

引子:有这样一个程序需求,做一个文本编辑器,读取文件内容后能够进行文字拼写检查,语法检查,字数统计等工作。设计要点:①必须等到读取文件内容完全之后才能进行之后的操作②为了提高程序效率,拼写检查,语法检查,字数统计等工作最好一起进行,或者根据需求每个任务单独进行。

看到上面的需要,第一眼我们的反应是用多线程可以解决,针对该程序,利用事件内核对象将比较容易的实现。下面给出代码:

#include "stdafx.h"#include <Windows.h>#include <process.h>HANDLE g_hEvent = NULL ;int s_n1 = 20 ;int s_n2 = 20 ;int s_n3 = 20 ;DWORD WINAPI WordCount(LPVOID lp) ;DWORD WINAPI SpellCheck(LPVOID lp) ;DWORD WINAPI GrammarCheck(LPVOID lp) ;void OpenFileAndReadContentsIntoMemory() {Sleep(3000) ;printf("Ready Go!!!\n") ;}int _tmain(int argc, _TCHAR* argv[]){g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL) ;ResetEvent(g_hEvent) ;HANDLE hThrd[3] ;DWORD dwThreadId[3] ;hThrd[0] = CreateThread(NULL, 0, WordCount, NULL, 0, &dwThreadId[0]) ;hThrd[1] = CreateThread(NULL, 0, SpellCheck, NULL, 0, &dwThreadId[1]) ;hThrd[2] = CreateThread(NULL, 0, GrammarCheck, NULL, 0, &dwThreadId[2]) ;OpenFileAndReadContentsIntoMemory() ;SetEvent(g_hEvent) ;while(TRUE){//必须有这段代码,否则主线程退出了整个程序就退出了,后面的过程就无法实现了}return 0;}DWORD WINAPI WordCount(LPVOID lp) {WaitForSingleObject(g_hEvent, INFINITE) ;while(s_n1-- > 0){Sleep(1000) ;printf("WordCouting %d...\n", s_n1) ;}return 0 ;}DWORD WINAPI SpellCheck(LPVOID lp) {WaitForSingleObject(g_hEvent, INFINITE) ;while(s_n2-- > 0){Sleep(1000) ;printf("SpellChecking %d...\n", s_n2) ;}return 0 ;}DWORD WINAPI GrammarCheck(LPVOID lp) {WaitForSingleObject(g_hEvent, INFINITE) ;while(s_n3-- > 0){Sleep(1000) ;printf("GrammarChecking %d...\n", s_n3) ;}return 0 ;}

下面进行分析:

如何做到内容读取完全之后才开始后面的任务操作?

我们在程序的开始创建WordCount、SpellCheck、GrammarCheck线程之后,他们都各自跑了起来,难道不用担心

OpenFileAndReadContentsIntoMemory()函数没有执行完吗,如果该函数没有执行完,那么后面读取的内容就不完整,程序出现bug了!!!

不用担心,由于我们创建事件内核对象时,CreateEvent的第三个参数表明他的初始化状态是没有触发的,请看每个任务线程函数的第一行代码:WaitForSingleObject(g_hEvent, INFINITE) 。该函数一直会等待g_hEvent变为触发状态,否则该线程阻塞,不会往下执行。您看,

OpenFileAndReadContentsIntoMemory()函数执行完之后,调用了SetEvent(g_hEvent) ,该函数的目的就是使g_hEvent变为触发状态,

那么各个任务线程就开始工作了。是不是比较清晰呢:-D

我们再来讨论第二个问题:由于某个用户的机器配置太烂,WordCount、SpellCheck、GrammarCheck三个任务一起执行,

我们的程序看起来比较卡,老板要你改方案。是不是要做很多复杂的操作呢?

不用!时间内核对象的好处就体现在这里了,容我慢慢到来。

有没有注意CreateEvent第二个参数,他是什么意思呢?为TRUE表明创建的是人工重置事件对象,为False则是自动重置事件对象。嘛?人工?自动?都是一些啥啊?

哈哈,自动重置事件对象就是当成功地调用WaitForSingleObject()后,g_hEvent会自动重置为非触发状态。

那么WordCount、SpellCheck、GrammarCheck中某一个线程成功地调用WaitForSingleObject()后,

g_hEvent会自动重置为非触发状态,其他的两个线程只能等待他孤单的执行了,~~~~(>_<)~~~~

慢着,这样程序就能单独的执行每个线程啦?聪明的朋友一定会说,既然g_hEvent都是非触发状态了,

后面等待的线程肯定没有机会执行,他们都饿死了。是的,的确是这样。您也一定也知道了在哪里改写代码了吧。对,就是在每个线程执行完之后再调用SetEvent。

0 0
原创粉丝点击