2011-02-14 61 views
1

我需要使用事件同步線程。首先,我沒有在Windows中獲得事件的概念。我會舉一個例子,我有主線程和輔助線程。我創建了兩個名爲「寫」和「測試」的事件。在主線程中,我發出'write'事件的信號,並在「測試」事件中等待,這兩個事件都得到了信號通知使用Windows中的事件同步線程

基本上我正在將一個應用程序從linux移植到windows,linux程序使用condition變量。線程條件變量在窗口XP提供

例如:。

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

#define THREADCOUNT 1 

HANDLE ghWriteEvent; 
HANDLE ghtestEvent; 
HANDLE ghThreads[THREADCOUNT]; 

DWORD WINAPI ThreadProc(LPVOID); 

void CreateEventsAndThreads(void) 
{ 
    int i; 
    DWORD dwThreadID; 

    ghWriteEvent = CreateEvent(
     NULL,    // default security attributes 
     TRUE,    // manual-reset event 
     FALSE,    // initial state is nonsignaled 
     TEXT("WriteEvent") // object name 
     ); 

    if (ghWriteEvent == NULL) 
    { 
     printf("CreateEvent failed (%d)\n", GetLastError()); 
     return; 
    } 

    ghtestEvent = CreateEvent(
     NULL,    // default security attributes 
     FALSE,    // manual-reset event 
     FALSE,    // initial state is nonsignaled 
     TEXT("WriteEvent") // object name 
     ); 

    if (ghtestEvent == NULL) 
    { 
     printf("CreateEvent failed (%d)\n", GetLastError()); 
     return; 
    } 

    // Create multiple threads to read from the buffer. 

    for(i = 0; i < THREADCOUNT; i++) 
    { 
     // TODO: More complex scenarios may require use of a parameter 
     // to the thread procedure, such as an event per thread to 
     // be used for synchronization. 
     ghThreads[i] = CreateThread(
      NULL,    // default security 
      0,     // default stack size 
      ThreadProc,  // name of the thread function 
      NULL,    // no thread parameters 
      0,     // default startup flags 
      &dwThreadID); 

     if (ghThreads[i] == NULL) 
     { 
      printf("CreateThread failed (%d)\n", GetLastError()); 
      return; 
     } 
    } 
} 

void WriteToBuffer(VOID) 
{ 
    DWORD dwWaitResult; 
    printf("Main thread writing to the shared buffer...\n"); 

    printf("Posting Events for %d\n",ghWriteEvent); 

    // Set ghWriteEvent to signaled 
    if (! SetEvent(ghWriteEvent)) 
    { 
     printf("SetEvent failed (%d)\n", GetLastError()); 
     return; 
    } 

    dwWaitResult= WaitForSingleObject(
          ghtestEvent, // event handle 
          INFINITE); // indefinite wait 

    printf("WaitForSingleObject signelled (%d)\n", GetLastError()); 

    if (dwWaitResult == WAIT_OBJECT_0) 
    printf("Signlled State for %d with ret val : %d\n",ghtestEvent,dwWaitResult); 
} 

void CloseEvents() 
{ 
    // Close all event handles (currently, only one global handle). 

    CloseHandle(ghWriteEvent); 
} 

int main(void) 
{ 
    DWORD dwWaitResult; 

    CreateEventsAndThreads(); 

    WriteToBuffer(); 

    printf("Main thread waiting for threads to exit...\n"); 

    // The handle for each thread is signaled when the thread is 
    // terminated. 
    dwWaitResult = WaitForMultipleObjects(
     THREADCOUNT, // number of handles in array 
     ghThreads,  // array of thread handles 
     TRUE,   // wait until all are signaled 
     INFINITE); 

    switch (dwWaitResult) 
    { 
     // All thread objects were signaled 
     case WAIT_OBJECT_0: 
      printf("All threads ended, cleaning up for application exit...\n"); 
      break; 

     // An error occurred 
     default: 
      printf("WaitForMultipleObjects failed (%d)\n", GetLastError()); 
      return 1; 
    } 

    // Close the events to clean up 

    CloseEvents(); 

    return 0; 
} 

DWORD WINAPI ThreadProc(LPVOID lpParam) 
{ 
    // lpParam not used in this example. 
    UNREFERENCED_PARAMETER(lpParam); 

    DWORD dwWaitResult; 

    printf("Thread %d waiting for write event...\n", GetCurrentThreadId()); 

    dwWaitResult = WaitForSingleObject(
         ghWriteEvent, // event handle 
         INFINITE); // indefinite wait 

    printf("rcvd event for Write is %d \n", ghWriteEvent); 
    switch (dwWaitResult) 
    { 
     // Event object was signaled 
     case WAIT_OBJECT_0: 
       WaitForSingleObject(
           ghtestEvent, // event handle 
           INFINITE); // indefinite wait 

      printf("rcvd event for %d with Error %d\n", ghtestEvent,GetLastError()); 

      if (dwWaitResult == WAIT_OBJECT_0) 
      { 
       printf("Test event signaled for second thread \n"); 
      } 
      break; 

     // An error occurred 
     default: 
      printf("Wait error (%d)\n", GetLastError()); 
      printf("Wait error (%d)\n", GetLastError()); 
      return 0; 
    } 

    printf("Thread %d exiting\n", GetCurrentThreadId()); 
    return 1; 
} 

Output of the program is: 
Main thread writing to the shared buffer... 
Posting Events for 2012 
WaitForSingleObject signelled (183) 
Signlled State for 2008 with ret val : 0 
Main thread waiting for threads to exit... 
Thread 2016 waiting for write event... 
rcvd event for Write is 2012 
rcvd event for 2008 with Error 0 
Test event signaled for second thread 
Thread 2016 exiting 
All threads ended, cleaning up for application exit... 

回答

3

了長期的鬥爭,我發現了原因後,如果兩個事件具有相同的名稱創建,在創建第二個事件將引發一個錯誤「ERROR_ALREADY_EXISTS(183)。

如果使用不同的名稱創建事件,它的工作原理沒有任何問題。檢查錯誤並相應地執行是一個很好的編程。

ghtestEvent = CreateEvent(
    NULL,    // default security attributes 
    FALSE,    // manual-reset event 
    FALSE,    // initial state is nonsignaled 
    TEXT("WriteEvent") // object name 
    ); 
if (ERROR_ALREADY_EXISTS == GetLastError()) 
{ 
     printf("unable to create event (%d)\n".GetLastError()); 
     exit(0); 
}  

問候 杜琪峯

+1

總是檢查錯誤!在你的情況下,你爲什麼需要命名事件。你可以匿名。 – 2011-02-14 14:24:12

1

你只需要如果你打算使用它們進程間通信命名事件。如果您只是單個進程中的同步線程,則可以傳遞NULL作爲名稱。

當我爲進程間通信創建命名同步對象時,我通常給它們一個描述性的名稱(如「MyCompany-MyApp-WriteEvent」),並在GUID上加上一個很好的措施。您不想與名爲他的事件「WriteEvent」的其他開發人員發生名稱衝突。該名稱最長可達MAX_PATH個字符,並且不會影響性能。