WaitForSingleObjec等待Event成功引起的副作用


一個自動重置事件的對象,WaitForSingleObject在等待成功以后會把事件對象設置為未觸發狀態(馬上調用ResetEvent()函數),而手動設置事件對象不會有這個副作用。

#include <iostream>
#include <process.h>
#include <windows.h>
#include <string>
using std::cout;
using std::endl;
using std::string;

const int num=10;
int count;
HANDLE ThreadEvent;
unsigned __stdcall ThreadFun(void* par);

int main()
{
    //創建內核事件對象(自動重置,未激活狀態)
    ThreadEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
    HANDLE handles[num];
    for(int i=0;i<num;++i)
    {
        handles[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,NULL,0,0);
        WaitForSingleObject(ThreadEvent,INFINITE);
        //自動激活狀態的事件,WaitForSingleObject帶來的副作用就是會自己調用ResetEvent()將事件設置為未激活
    }
    for(int i=0;i<num;++i)
        CloseHandle(handles[i]);
    CloseHandle(ThreadEvent);//關閉內核事件對象
    system("PAUSE");
    return 0;
}
unsigned __stdcall ThreadFun(void* par)
{
    cout<<"count:"<<++count<<endl;
    SetEvent(ThreadEvent);//設置事件為激活狀態
    return 0;
}

把事件對象設置為手動重置,就需要我們手動重置事件狀態。

int main()
{
    //創建內核事件對象(手動重置,未激活狀態)
    ThreadEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
    HANDLE handles[num];
    for(int i=0;i<num;++i)
    {
        handles[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,NULL,0,0);
        WaitForSingleObject(ThreadEvent,INFINITE);
        //手動激活的事件,WaitForSingleObject不會重置事件為未激活。
        ResetEvent(ThreadEvent);//手動重置事件對象為未激活狀態
    }
    for(int i=0;i<num;++i)
        CloseHandle(handles[i]);
    CloseHandle(ThreadEvent);//關閉內核事件對象
    system("PAUSE");
    return 0;
}

上面代碼內核事件對象為手動重置,所以在WaitForSingleObject以后需要手動調用ResetEvent(),如果把ResetEvent(ThreadEvent);注釋掉,那么所以等待線程都會被觸發,導致同步失敗。

    for(int i=0;i<num;++i)
    {
        handles[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,NULL,0,0);
        WaitForSingleObject(ThreadEvent,INFINITE);
        //手動激活的事件,WaitForSingleObject不會重置事件為未激活。
        //ResetEvent(ThreadEvent);//后面的線程都會很順利的執行,事件對象一直為激活狀態
    }

線程執行同步失敗,輸出混亂,可以將num變量設置大點,這樣更加容易出現混亂輸出。

本文版權歸kennyMc和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM