2012-03-05 7 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

コードに悪い匂いが1つあります。 'ResetEvent'への呼び出しは、(自動リセットイベントを使用しているため)無駄なものであり、最悪の場合、イベントが失われてデッドロックが発生する可能性があります。単にそれらを削除してください。 – arx

+0

@arx実際には、 'Server'スレッドがそのイベントを通知する前に、メインスレッドが次の繰り返しに対して' SetEvent'を実行できないので、 'Server'スレッドが誤ってそれ自身のイベントをリセットすることはできません。しかし、私は彼がマニュアルイベントに切り替えるか、リセットを解除する必要があることに同意します。 – Tudor

答えて

1

はい、このコードは正しいです。

この例は、イベントの仕組みを確認するのに便利です。しかし、生産コードを書くときには、ホイールを改革する必要はありません。例えば、説明したインタラクションは、Intel TBBライブラリーのような同時データ構造を使用してエレガントにモデル化することができます。 concurrent_bounded_queue

関連する問題