免费高清特黄a大片,九一h片在线免费看,a免费国产一级特黄aa大,国产精品国产主播在线观看,成人精品一区久久久久,一级特黄aa大片,俄罗斯无遮挡一级毛片

分享

CreateEvent的用法

 oskycar 2014-01-12

 CreateEvent的用法收藏

新一篇: PreCreateWindow的作用和使用方法 | 舊一篇: VC中_T()的作用

事件對象就像一個開關:它只有兩種狀態(tài)---開和關。當一個事件處于”開”狀態(tài),我們稱其為”有信號”否則稱為”無信號”??梢栽谝粋€線程的執(zhí)行函數(shù)中創(chuàng)建一個事件對象,然后觀察它的狀態(tài),如果是”無信號”就讓該線程睡眠,這樣該線程占用的CPU時間就比較少。

產(chǎn)生事件對象的函數(shù)如下:  

HANDLE     CreateEvent(

        LPSECURITY_ATTRIBUTES     lpEventAttributes,     //     SD   
        BOOL     bManualReset,                                                 //     reset     type   
        BOOL     bInitialState,                                                      //     initial     state   
        LPCTSTR     lpName                                                       //     object     name   
    );   
    該函數(shù)創(chuàng)建一個Event同步對象,如果CreateEvent調(diào)用成功的話,會返回新生成的對象的句柄,否則返回NULL。

參數(shù)說明:
    lpEventAttributes     一般為NULL   


    bManualReset               創(chuàng)建的Event是自動復位還是人工復位.如果true,人工復位,   一旦該Event被設置為有信號,則它一直會等到ResetEvent()API被調(diào)用時才會恢復 為無信號.     如果為false,Event被設置為有信號,則當有一個wait到它的Thread時,  該Event就會自動復位,變成無信號.   如果想 在每次調(diào)用WaitForSingleObject 后讓WINDOWS為您自動地把事件地狀態(tài)恢復為”無信號”狀態(tài),必須把該參數(shù)設為FALSE,否則,您必須每次調(diào)用ResetEvent函數(shù)來清除事件 的信號。


    bInitialState             初始狀態(tài),true,有信號,false無信號   
    lpName                  事件對象的名稱。您在OpenEvent函數(shù)中可能使用。

注釋:
    一個Event被創(chuàng)建以后,可以用OpenEvent()API來獲得它的Handle,用CloseHandle()    來關閉它,用SetEvent()或PulseEvent()來設置它使其有信號,用ResetEvent()       來使其無信號,用WaitForSingleObject()或WaitForMultipleObjects()來等待其變?yōu)橛行盘?   
   
    PulseEvent()是一個比較有意思的使用方法,正如這個API的名字,它使一個Event 對象的狀態(tài)發(fā)生一次脈沖變化,從無信號變成有信號再變成無信號,而整個操作是原子的.   
    對自動復位的Event對象,它僅釋放第一個等到該事件的thread(如果有),而對于人工復位的Event對象,它釋放所有等待的thread.  
 

 
這里有兩個API函數(shù)用來修改事件對象的信號狀態(tài):SetEvent和ResetEvent。前者把事件對象設為”有信號”狀態(tài),而后者正好相反。
在事件對象生成后,必須調(diào)用WaitForSingleObject來讓線程進入等待狀態(tài),該函數(shù)的語法如下:  

WaitForSingleObject proto hObject:DWORD, dwTimeout:DWORD  

hObject -->指向同步對象的指針。事件對象其實是同步對象的一種。
dwTimeout --> 等待同步對象變成”有信號”前等待的時間,以毫秒計。當?shù)却臅r間超過該值后無信號同步對象仍處于”無信號”狀態(tài),線程不再等待, WaitForSingleObject函數(shù)會返回。如果想要線程一直等待,請把該參數(shù)設為INFINITE(該值等于0xffffffff)。  

發(fā)表于 @ 2008年04月18日 13:30:00|評論(0)|編輯

新一篇: PreCreateWindow的作用和使用方法 | 舊一篇: VC中_T()的作用



 Visual C++中的多線程收藏

新一篇: 特洛伊木馬(一) | 舊一篇: 用戶接口與作業(yè)調(diào)度

以前,曾經(jīng)研究過了java中的多線程問題,特別是加鎖和同步問題,但是,在C++中,確沒有這么簡單了。由于C沒有提供像java里的線程類,一些同步的實現(xiàn)必須靠自己程序?qū)崿F(xiàn),稍顯復雜。
一般來說,在C++里面創(chuàng)建和終止線程的函數(shù)為:_beginthread和_endthread兩個函數(shù),當然,也可以用CreateThread和ExitThread。具體的使用方式可以查看msdn。
那么,怎么樣實現(xiàn)加鎖與同步呢?可以使用createMutex函數(shù)以及createEvent方法等來實現(xiàn),具體可以參考下例:

#include < iostream>
#include < windows.h>

using namespace std;
#define BUFSIZE 5
int SharedBuffer[BUFSIZE];
int head,tail;
int count;
HANDLE hMutex;
HANDLE hNotFullEvent, hNotEmptyEvent;
void BB_Producer()
{
int i;
for (i=20; i>=0; i--) {
while(1) {
WaitForSingleObject(hMutex,INFINITE);
if (count == BUFSIZE) { // 緩沖區(qū)滿
ReleaseMutex(hMutex);
// 等待直到緩沖區(qū)非滿
WaitForSingleObject(hNotFullEvent,INFINITE);
continue;
}
// 得到互斥鎖且緩沖區(qū)非滿,跳出while循環(huán)
break;
}
// 得到互斥鎖且緩沖區(qū)非滿,開始產(chǎn)生新數(shù)據(jù)
cout << "Produce: " << i << endl;
SharedBuffer[tail] = i;
tail = (tail+1) % BUFSIZE;
count++;
ReleaseMutex(hMutex); // 結(jié)束臨界區(qū)
PulseEvent(hNotEmptyEvent); // 喚醒消費者線程
}
}
void BB_Consumer()
{
int result;
while (1) {
WaitForSingleObject(hMutex,INFINITE);
if (count == 0) { // 沒有可以處理的數(shù)據(jù)
ReleaseMutex(hMutex); // 釋放互斥鎖且等待
// 等待直到緩沖區(qū)非空
WaitForSingleObject(hNotEmptyEvent,INFINITE);
}
else if (SharedBuffer[head] == 0) {
cout << "Consumed 0: end of data" << endl;
ReleaseMutex(hMutex); // 結(jié)束臨界區(qū)
ExitThread(0);
}
else { // 獲得互斥鎖且緩沖區(qū)有數(shù)據(jù),開始處理
result = SharedBuffer[head];
cout << "Consumed: " << result << endl;
head = (head+1) % BUFSIZE;
count--;
ReleaseMutex(hMutex); // 結(jié)束臨界區(qū)
PulseEvent(hNotFullEvent); // 喚醒生產(chǎn)者線程
}
}
}
void main()
{
HANDLE hThreadVector[2];
DWORD ThreadID;
count = 0;
head = 0;
tail = 0;
hMutex = CreateMutex(NULL,FALSE,NULL);
hNotFullEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
hNotEmptyEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
hThreadVector[0] = CreateThread (NULL, 0,
(LPTHREAD_START_ROUTINE) BB_Producer,
NULL, 0, (LPDWORD)&ThreadID);
hThreadVector[1] = CreateThread (NULL, 0,
(LPTHREAD_START_ROUTINE) BB_Consumer,
NULL, 0, (LPDWORD)&ThreadID);
WaitForMultipleObjects(2,hThreadVector,TRUE,INFINITE);
}
這是一個典型的生產(chǎn)者-消費者問題,它們公用的資源是SharedBuffer,當Buffer中有數(shù)據(jù)且未滿時,兩個線程都可以運行,當Buffer為 空時,Consumer就要等待,直到Buffer不為空,這里就是用event來實現(xiàn)的;同樣,當Buffer為滿時,Producer就要等待。

發(fā)表于 @ 2006年10月29日 19:54:00|評論(2)|編輯

新一篇: 特洛伊木馬(一) | 舊一篇: 用戶接口與作業(yè)調(diào)度


Windows API一日一練(45)CreateEvent和SetEvent函數(shù)收藏

新一篇: Windows API一日一練(46)EnterCriticalSection和LeaveCriticalSection函數(shù) | 舊一篇: Windows API一日一練(44)wsprintf函數(shù)

當你創(chuàng)建一個線程時,其實那個線程是一個循環(huán),不像上面那樣只運行一次的。這樣就帶來了一個問題,在那個死循環(huán)里要找到合適的條件退出那個死循環(huán),那么是怎么樣實現(xiàn)它的呢?在Windows里往往是采用事件的方式,當然還可以采用其它的方式。在這里先介紹采用事件的方式來通知從線程運行函數(shù)退出來,它的實現(xiàn)原理是這樣,在那個死循環(huán)里不斷地使用WaitForSingleObject函數(shù)來檢查事件是否滿足,如果滿足就退出線程,不滿足就繼續(xù)運行。當在線程里運行阻塞的函數(shù)時,就需要在退出線程時,先要把阻塞狀態(tài)變成非阻塞狀態(tài),比如使用一個線程去接收網(wǎng)絡數(shù)據(jù),同時使用阻塞的SOCKET時,那么要先關閉SOCKET,再發(fā)送事件信號,才可以退出線程的。下面就來演示怎么樣使用事件來通知線程退出來。
函數(shù)CreateEvent聲明如下:
WINBASEAPI
__out
HANDLE
WINAPI
CreateEventA(
    __in_opt LPSECURITY_ATTRIBUTES lpEventAttributes,
    __in     BOOL bManualReset,
    __in     BOOL bInitialState,
    __in_opt LPCSTR lpName
    );
WINBASEAPI
__out
HANDLE
WINAPI
CreateEventW(
    __in_opt LPSECURITY_ATTRIBUTES lpEventAttributes,
    __in     BOOL bManualReset,
    __in     BOOL bInitialState,
    __in_opt LPCWSTR lpName
    );
#ifdef UNICODE
#define CreateEvent CreateEventW
#else
#define CreateEvent CreateEventA
#endif // !UNICODE
lpEventAttributes是事件的屬性。
bManualReset是指事件手動復位,還是自動復位狀態(tài)。
bInitialState是初始化的狀態(tài)是否處于有信號的狀態(tài)。
lpName是事件的名稱,如果有名稱,可以跨進程共享事件狀態(tài)。
調(diào)用這個函數(shù)的例子如下:
#001 #pragma once
#002 
#003 //線程類。
#004 //蔡軍生 2007/09/23 QQ:9073204
#005 class CThread
#006 {
#007 public:
#008 
#009  CThread(void)
#010  {
#011          m_hThread = NULL;
#012          m_hEventExit = NULL;
#013  }
#014 
#015  virtual ~CThread(void)
#016  {
#017         if (m_hThread)
#018         {
#019               //刪除的線程資源。
#020               ::CloseHandle(m_hThread);
#021         }
#022 
#023         if (m_hEventExit)
#024         {
#025               //刪除事件。
#026               ::CloseHandle(m_hEventExit);
#027         }
#028        
#029  }
#030 
#031  //創(chuàng)建線程
#032  HANDLE CreateThread(void)
#033  {
#034         //創(chuàng)建退出事件。
#035         m_hEventExit = ::CreateEvent(NULL,TRUE,FALSE,NULL);
#036         if (!m_hEventExit)
#037          {
#038               //創(chuàng)建事件失敗。
#039               return NULL;
#040         }
#041 
#042         //創(chuàng)建線程。
#043          m_hThread = ::CreateThread(
#044               NULL,                    //安全屬性使用缺省。
#045               0,                         //線程的堆棧大小。
#046               ThreadProc,                 //線程運行函數(shù)地址。
#047               this,                      //傳給線程函數(shù)的參數(shù)。
#048               0,                         //創(chuàng)建標志。
#049               &m_dwThreadID);        //成功創(chuàng)建后的線程標識碼。
#050 
#051         return m_hThread;
#052  }
#053 
#054  //等待線程結(jié)束。
#055  void WaitFor(DWORD dwMilliseconds = INFINITE)
#056  {
#057         //發(fā)送退出線程信號。
#058        ::SetEvent(m_hEventExit);
#059 
#060         //等待線程結(jié)束。
#061         ::WaitForSingleObject(m_hThread,dwMilliseconds);
#062  }
#063 
#064 protected:
#065  //
#066  //線程運行函數(shù)。
#067  //蔡軍生 2007/09/21
#068  //
#069  static DWORD WINAPI ThreadProc(LPVOID lpParameter)
#070  {
#071         //轉(zhuǎn)換傳送入來的參數(shù)。
#072         CThread* pThread = reinterpret_cast<CThread *>(lpParameter);
#073         if (pThread)
#074         {
#075               //線程返回碼。
#076               //調(diào)用類的線程處理函數(shù)。
#077               return pThread->Run();
#078         }
#079        
#080         //
#081         return -1;       
#082  }
#083 
#084  //線程運行函數(shù)。
#085  //在這里可以使用類里的成員,也可以讓派生類實現(xiàn)更強大的功能。
#086  //蔡軍生 2007/09/25
#087  virtual DWORD Run(void)
#088  {
#089         //輸出到調(diào)試窗口。
#090         ::OutputDebugString(_T("Run()線程函數(shù)運行/r/n"));     
#091 
#092         //線程循環(huán)。
#093         for (;;)
#094         {
#095              DWORD dwRet = WaitForSingleObject(m_hEventExit,0);
#096               if (dwRet == WAIT_TIMEOUT)
#097               {
#098                    //可以繼續(xù)運行。                
#099                    TCHAR chTemp[128];
#100                    wsprintf(chTemp,_T("ThreadID=%d/r/n"),m_dwThreadID);
#101                    ::OutputDebugString(chTemp);
#102 
#103                     //目前沒有做什么事情,就讓線程釋放一下CPU。
#104                    Sleep(10);
#105               }
#106               else if (dwRet == WAIT_OBJECT_0)
#107               {
#108                    //退出線程。
#109                    ::OutputDebugString(_T("Run() 退出線程/r/n"));
#110                    break;
#111               }
#112               else if (dwRet == WAIT_ABANDONED)
#113               {
#114                    //出錯。
#115                    ::OutputDebugString(_T("Run() 線程出錯/r/n"));
#116                    return -1;
#117               }
#118         }
#119 
#120         return 0;
#121  }
#122 
#123 protected:
#124  HANDLE m_hThread;         //線程句柄。
#125  DWORD m_dwThreadID;          //線程ID。
#126 
#127  HANDLE m_hEventExit;    //線程退出事件。
#128 };
#129 
上面在第35行創(chuàng)建線程退出事件,第95行檢查事件是否可退出線程運行,第58行設置退出線程的事件。
 

發(fā)表于 @ 2007年09月25日 21:32:00|評論(0)|編輯

新一篇: Windows API一日一練(46)EnterCriticalSection和LeaveCriticalSection函數(shù) | 舊一篇: Windows API一日一練(44)wsprintf函數(shù)


Win32 API 常用函數(shù)之二收藏

新一篇: Win32 API 常用函數(shù)之三——注冊表操作(上) | 舊一篇: Win32 API 常用函數(shù)之一

【事件】
       事件用處多是控制線程間的同步。
       最典型的應用就是CreateThread之后等待線程函數(shù)的啟動。如Main線程里CreateThread,它之后的操作依賴于子線程,那么它一般會 在CreateThread之后判斷HANDLE是否有效,然后進入等待。(當然在這之前,一個Event是已經(jīng)創(chuàng)建好的,并初始化為未通知狀態(tài))子線程 啟動后完成了初始化操作,并設置Event為已通知狀態(tài)。這時,一直在等待該事件的Main線程發(fā)現(xiàn)該事件已經(jīng)得到通知,因此它就變成可調(diào)度線程。這時 Main線程知道子線程已經(jīng)完成了初始化操作。
       CreateEvent函數(shù)用于創(chuàng)建一個Event,其原型如下:
HANDLE CreateEvent(
  LPSECURITY_ATTRIBUTES lpEventAttributes, 
  BOOL bManualReset, 
  BOOL bInitialState, 
  LPTSTR lpName 
); 
       參數(shù)說明:
  1. 第一個參數(shù)同CreateThread類似,也是安全級別相關,通常被被設置為NULL,以獲得默認的安全級別。
  2. 第二個參數(shù)是個布爾值,它能夠告訴系統(tǒng)是創(chuàng)建一個人工重置的事件(TRUE)還是創(chuàng)建一個自動重置的事件( FALSE)。
  3. 第三個參數(shù)也是布爾值,用于指明該事件是要初始化為已通知狀態(tài)(TRUE)還是未通知狀態(tài)(FALSE)。
  4. 第四個參數(shù)是一個字符串,用于標示這個事件的名字。
       以下是詳細說明:
  1. 已通知狀態(tài)和未通知狀態(tài)
    事件只有兩種狀態(tài),已通知表示這個事件已經(jīng)被設置過了(可以理解為發(fā)生了),未通知表示還沒有發(fā)生。一般設置為未通知狀態(tài),并由SetEvent設置為已 通知狀態(tài)。當然也可以反著做,CreateEvent時設置為已通知狀態(tài),然后由ResetEvent設置為未通知狀態(tài)。
  2. 人工重置與自動重置
    自動重置的事件定義了應該成功等待的副作用規(guī)則,即當線程成功地等待到該對象時,自動重置的事件就會自動重置到未通知狀態(tài)。
    人工重置則需要調(diào)用ResetEvent函數(shù)設置為未通知狀態(tài)。
  3. 名字共享
    這個參數(shù)很重要,Win32 API中有很多方法有這個參數(shù),它遵從一種按名字共享的規(guī)則。
    如果傳入一個非NULL字符串(最多260個字符),那么在全局空間,共享該HANDLE,這個全局可以是跨進程的名字空間,即在另一個進程中依然能夠使用該名字的HANDLE。
    如果希望避免這種全局范圍內(nèi)的共享,那么應該傳入NULL,以一種匿名的方式創(chuàng)建Event等,這樣,它只在當前線程內(nèi)可見。
        當進程A創(chuàng)建了一個Event后,如CreateEvent(NULL,F(xiàn)ALSE,F(xiàn)LASE,_T(“UniqueEvent”));進程B同樣創(chuàng)建 了一個Event,也想起名字為UniqueEvent,那么就會出現(xiàn)問題:CreateEvent(NULL,F(xiàn)ALSE,F(xiàn)ALSE,_T (“UniqueEvent”));系統(tǒng)會首先查看是否已經(jīng)存在了一個名字為“UniqueEvent”的對象,由于確實存在了一個帶有改名字的內(nèi)核對 象,因此內(nèi)核要檢查對象類型,同樣是一 個Event,那么系統(tǒng)會執(zhí)行一次安全檢查,以確定調(diào)用者是否擁有對該對象的完整訪問權(quán)。如果有這種訪問權(quán),系統(tǒng)會在進程B的句柄表里找到一個空項目,對 其初始化,使得該項指向現(xiàn)有的內(nèi)核對象。如果類型不匹配,或者拒絕訪問,那么進程B的CreateEvent會失敗。
       應用程序能夠確定它是否確實創(chuàng)建了一個新內(nèi)核對象,而不是打開了一個現(xiàn)有的對象。方法是在調(diào)用C r e a t e *函數(shù)后立即調(diào)用G e t L a s t E r r o r:如果為ERROR_ALREADY_EXISTS,那么表示系統(tǒng)內(nèi)已經(jīng)存在了這樣名字的對象。
       Open*是去查看名字空間中是否有這個名字的內(nèi)核對象存在調(diào)用C r e a t e *函數(shù)與調(diào)用O p e n *函數(shù)之間的主要差別是,如果對象并不存在,那么C r e a t e *函數(shù)將創(chuàng)建該對象,而O p e n *函數(shù)則運行失敗。

       PulseEvent函數(shù)使得事件變?yōu)橐淹ㄖ獱顟B(tài),然后立即又變?yōu)槲赐ㄖ獱顟B(tài),這就像在調(diào)用SetEvent后又立即調(diào)用ResetEvent函數(shù)一樣。 如果在人工重置的事件上調(diào)用PulseEvent函數(shù),那么在發(fā)出該事件時,等待該事件的任何一個線程或所有線程將變?yōu)榭烧{(diào)度線程。如果在自動重置事件上 調(diào)用P u l s e E v e n t函數(shù),那么只有一個等待該事件的線程變?yōu)榭烧{(diào)度線程。如果在發(fā)出事件時沒有任何線程在等待該事件,那么將不起任何作用。

【等待函數(shù)】
       等待函數(shù)用來監(jiān)聽事件的已通知狀態(tài)。WaitForSingleObject和WaitForMultipleObjects兩個函數(shù)分別用以等待單個事件和多個事件。
DWORD WaitForSingleObject(
  HANDLE hHandle,
  DWORD dwMilliseconds
);
DWORD WaitForMultipleObjects(
  DWORD nCount,
  const HANDLE* lpHandles,
  BOOL bWaitAll,
  DWORD dwMilliseconds
);
       從函數(shù)原型上來看可知,事件的含義是能夠支持被通知/未通知的內(nèi)核對象(例如進程和線程,當傳入的是進程或者線程句柄時,他表示等該線程或進程被標識為終止運行為止。)。
       dwMilliseconds 參數(shù)表明等待的時間,如果在這個時間段中事件為已通知狀態(tài),那么對于Single版本將返回WAIT_OBJECT_0,對于Multiple版本將返回 WAIT_OBJECT_0 to (WAIT_OBJECT_0 + nCount– 1)。如果沒有等到將返回WAIT_TIMEOUT。
       Multiple版本中的bWaitAll表示想要讓它使用何種方式等待。如果為該參數(shù)傳遞TRUE,那么在所有對象變?yōu)橐淹ㄖ獱顟B(tài)之前,該函數(shù)將不允許調(diào)用線程運行。一般是FALSE,即只要有一個事件被相應,則線程可調(diào)度。

      

發(fā)表于 @ 2007年10月28日 18:04:00|評論(0)|編輯

新一篇: Win32 API 常用函數(shù)之三——注冊表操作(上) | 舊一篇: Win32 API 常用函數(shù)之一

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多