2011-12-19 7 views
8

グラフィカルアプリケーションでは、コンソール入力を使用してデバッグコマンドを実行します。コンソールが作成されると、そのすべての入力を処理するユーザーコマンドを収集するための新しいスレッドも作成され、グラフィカルアプリケーションは並行して実行され続けます。 boost :: threadライブラリを使用します。cinが入力を待つのを止めることができますか?

これまではうまくいきましたが、このスレッドの実行を停止する良い解決策は見つかりませんでした。スレッドは、常にユーザーの入力を待っている:

while(appRunning) 
{ 
    std::cin>>theUserCommand; 
    // ...do stuff 
} 

グラフィカルアプリケーションが終了したときに続いて、それはすべてのコンソール機能を停止します、私はスレッドが含まれている:あなたが見ることができるように

appRunning = false; 
// do some more related clean up 
myListeningThread->join(); 

を結合が呼び出された後、std :: cinはユーザー入力を待つことになります。 私が試した解決策の1つは、「キー入力を合成する」というイベントを作成することです.STD :: CinはENTERで送信する値を取得し、スレッドはうまく終了します。このソリューションは恐ろしいものであり、保持したくありません。 さらに、ツールが実行される環境の1つで動作しましたが、UI APIと共に使用すると失敗します。あなたは私が正しい方法でこれを修正する方法を教えてくれますか?実際にC++のドキュメントにstd :: cinがユーザー入力を待っているのを止め、プログラムの実行を続行する機能があるのか​​どうかは確かに言えませんが、それは可能ですか?

編集:私は、keybd_eventは、WriteConsoleInputで入力ハンドラを明示的に指定すると、いくつかの環境で誤解を招くことがあります。

+0

複数の可能性がありますが、すべてがOSに依存します。このプログラムはどのオペレーティングシステム用ですか? – zwol

+0

Win/VStudio9.0、上記のソリューションでkeybd_eventを使用しましたが、OSに依存する場合は問題ありません。それを修正するために私にどのようにお勧めしますか? – notNullGothik

+0

ところで、SetConsoleCtrlHandlerは本当に私にとってはうまくいきません。これは、アプリケーションの処理を終了し、アプリケーションのクリーンアップをすべてスキップします。 – notNullGothik

答えて

1

私は多くのWindowsプログラマーではありませんが、私はUnixについてもっと知っています。そして、私は完全にboost::threadに慣れていません。それは言った、this MSDN pageの下部に助言をもとに、ここに私の推奨事項は次のとおりです。コンソール読み取りスレッドを作成する前に

  • event objectを作成します。
  • シャットダウンするときは、スレッドの->joinメソッドを呼び出す直前に、イベントオブジェクトのSetEventを呼び出します。
  • 変更WaitForMultipleObjectsはなくistream::operator>>に遮断するには、コンソール読み取りスレッドでメインループ、このような何か:

    for (;;) { 
        HANDLE h[2]; 
        h[0] = GetStdHandle(STD_INPUT_HANDLE); 
        h[1] = that_event_object_I_mentioned; 
        DWORD which = WaitForMultipleObjects(2, h, FALSE, INFINITE); 
    
        if (which == WAIT_OBJECT_0) 
         processConsoleCommand(); 
        else if (which == WAIT_OBJECT_0 + 1) 
         break; 
        else 
         abort(); 
    } 
    
  • このスレッドはWaitForMultipleObjectsコール以外の任意のブロック操作を行うにはないように注意する必要があります。以下のコメントの議論では、を全く使用できないことを意味します。processConsoleCommandブロックしないようにするには、low-level console input functions(特にGetNumberOfConsoleInputEventsReadConsoleInput)を使用する必要があります。キャリッジリターンを読むまでは、processConsoleCommandへの多くのコールで文字を累積する必要があります。あなたも自分のエコーを行う必要があります。

+0

ブロッキングの読み込みを避けるために 'WaitForMultipleObjects()'を使って標準入力をブロックすることは基本的には信頼できないことに注意してください。標準入力がキーボード( 'CONIN $'デバイス)であれば、入力を生成しない 'CTRL 'などの任意のキーを押しても、次の入力操作をブロックするだけの待機をブロック解除し、スレッドはイベントの状態を無視します。詳細については、[関連する質問](http://stackoverflow.com/questions/8347642/checking-win32-file-streams-for-available-input)を参照してください。 –

+0

ユーザが入力しているときに、このスレッドが 'WaitForMultipleObjects'を回って回転しているかどうかは重要ではありません。 '' FIONREAD''(http://www.daemon-systems.org/man/ioctl.2.html)に相当するものがあると思いますが、 '' ReadFile''がブロックされないようにするために使うことができます。 Windowsはこれまでにも同様の機能がないため私に驚いています。このようなことができない場合は、GUI APIを使用して独自のコンソールウィンドウを実装する方法を検討しています。 – zwol

+0

...関連する質問の議論は本当に役に立たない。推奨は「コンソールから読み込む専用のスレッドを使用する」と思われます。ここでは、このようなスレッドを正確に実装する方法について説明します。 – zwol

関連する問題