私は、Win32 APIを使ってSTD_INPUT_HANDLEから読み込んだサブスレッドを作成し、読み込んだバイトをソケットにプッシュしようとしています。終了するときにこのスレッドを安全にシャットダウンできるようにするために、私はReadFileEx()を使用していて、プレーンな古いReadFile()の代わりにI/Oをオーバーラップしています。私のスレッドは、ReadFile()ではなくWaitForSingleObject()で待機し、メインスレッドがスレーブスレッドを遠ざけたい場合、そのオブジェクトに信号を送り、スレーブスレッドが起動して終了します。メインスレッドはシャットダウンシーケンスを続けることができます。Win32:STD_IN_HANDLEブロックのReadFileEx()はなぜですか?
私の問題は、ReadFileEx()が非同期で、ブロックされないことを示す文書にもかかわらず...私のスレーブスレッドはまだReadFileEx()内でブロックしています。 (私はprintfをイベントループに挿入して、どこがブロックされているかを確認しました)このため、メインスレッドはスレーブスレッドをシャットダウンできず、したがってメインプログラムは終了しません。
私は何か間違っているのですか、またはReadFileEx()がstdinから読み込むときにブロックすることを意味していますか?後者の場合、スレッドシャットダウン問題の解決策は何ですか?スレーブスレッドのエントリ関数は、あなたのpersualについては、以下である...
[... in the main thread, before the slave thread is spawned...]
_stdinHandle = GetStdHandle(STD_INPUT_HANDLE);
_wakeupSignal = CreateEvent(0, false, false, 0);
[...]
VOID WINAPI CompletedReadRoutine(DWORD dwErr, DWORD cbBytesRead, LPOVERLAPPED lpOverLap)
{
printf("CompletedReadRoutine dwErr=%li cbBytesRead=%li overlap=%p\n", dwErr, cbBytesRead, lpOverLap);
}
void StdinDataIO :: IOThreadEntry()
{
char buf[4096];
OVERLAPPED olap;
bool keepGoing = true;
bool overlappedReadPending = false;
while(keepGoing)
{
if (overlappedReadPending)
{
DWORD waitResult = WaitForSingleObjectEx(_wakeupSignal, INFINITE, true);
switch(waitResult)
{
case WAIT_IO_COMPLETION:
{
overlappedReadPending = false;
DWORD numBytesRead;
if ((GetOverlappedResult(_stdinHandle, &olap, &numBytesRead, true) == false)||(SendData(_slaveSocket, buf, numBytesRead, true) != numBytesRead)) keepGoing = false;
}
break;
default:
keepGoing = false;
break;
}
}
else
{
memset(&olap, 0, sizeof(olap));
if (ReadFileEx(_stdinHandle, buf, sizeof(buf), &olap, CompletedReadRoutine)) overlappedReadPending = true;
else keepGoing = false;
}
}
if (overlappedReadPending) CancelIo(_stdinHandle);
_slaveSocket.Reset(); // this alerts the main thread that we are gone
}
私は恐れていました。私はキーボードからだけでなく、親プロセスやファイルのリダイレクトも読むことができる必要があるので、CONIN $のトリックが私が望むことをするとは思わない –