2012-03-05 70 views
0

這是我第一次使用事件同步線程。我的代碼工作正常。但正如我經歷的那樣,它看起來不錯,但有明顯的缺陷,當我在更大的項目中使用這個概念時,這真的很難找到。使用事件來同步線程

所以我只是想問,這種使用事件來同步線程的方式對您來說看起來不錯嗎?

這個想法是我們有GetSymbol函數,它只能從主線程調用。服務器線程需要向主線程詢問這個函數的結果。

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

HANDLE symbol_need, symbol_ready, end; 

int symbol_container; 

int GetSymbol() 
{ 
    // Only main thread can use this function. 
    static int i = 0; 
    return ++i; 
} 

void Server(void* p) 
{ 
    printf("Ask for first symbol.\n"); 
    SetEvent(symbol_need); 

    DWORD wait_result; 

    wait_result = WaitForSingleObject(symbol_ready, INFINITE); 
    if(WAIT_OBJECT_0 == wait_result) 
    { 
     ResetEvent(symbol_ready); 
     printf("First symbol: %i\n", symbol_container); 
    } else { 
     printf("Something went wrong.\n"); 
    } 

    printf("Ask for second symbol.\n"); 
    SetEvent(symbol_need); 

    wait_result = WaitForSingleObject(symbol_ready, INFINITE); 
    if(WAIT_OBJECT_0 == wait_result) 
    { 
     ResetEvent(symbol_ready); 
     printf("Second symbol: %i\n", symbol_container); 
    } else { 
     printf("Something went wrong.\n"); 
    } 

    printf("OK, finish it."); 
    SetEvent(end); 
} 


int main(int argc, char* argv[]) 
{ 
    symbol_need = CreateEvent(NULL, FALSE, FALSE, NULL); 
    symbol_ready = CreateEvent(NULL, FALSE, FALSE, NULL); 
    end = CreateEvent(NULL, FALSE, FALSE, NULL); 

    _beginthread(Server, 0, NULL); 

    DWORD wait_result; 

    while(1) 
    { 
     wait_result = WaitForSingleObject(symbol_need, 100); 
     if(WAIT_OBJECT_0 == wait_result) 
     { 
      ResetEvent(symbol_need); 
      symbol_container = GetSymbol(); 
      SetEvent(symbol_ready); 
     } 
     wait_result = WaitForSingleObject(end, 100); 
     if(WAIT_OBJECT_0 == wait_result) 
     { 
      break; 
     } 
    } 
    return 0; 
} 
+1

該代碼有一個難聞的氣味。對ResetEvent的調用是多餘的(因爲您使用自動重置事件),最糟糕的情況是可能導致事件丟失,導致死鎖。只需刪除它們。 – arx 2012-03-05 23:20:48

+0

@arx實際上,由於主線程在「服務器」線程發出其事件之前無法爲下一次迭代執行「SetEvent」,因此「服務器」線程無法意外重置自己的事件。但我同意他應該切換到手動事件或刪除重置。 – Tudor 2012-03-05 23:30:48

回答

1

是的,這段代碼是正確的。

這個例子對於瞭解事件如何工作很有用。但是,當您編寫產品代碼時,不需要重新發明輪子。例如,您所描述的交互可以使用類似於英特爾TBB庫中的數據結構的併發數據結構進行優雅建模,例如concurrent_bounded_queue