2016-05-16 10 views
1

Ich habe ich Handgriff, der über stdinHandle = GetStdHandle(STD_INPUT_HANDLE), und ich habe separaten Thread, die solchen Code ausführen:win32: Wie stoppen Readfile (stdin | pipe)

while (!timeToExit) { 
    char ch; 
    DWORD readBytes = 0; 
    if (!::ReadFile(stdinHandle, &ch, sizeof(ch), &readBytes, nullptr)) { 
    //report error 
    return; 
    } 
    if (readBytes == 0) 
     break; 
    //handle new byte 
} 

wo timeToExitstd::atomic<bool> ist.

Ich möchte diesen Thread von einem anderen Thread zu stoppen. Ich habe es versucht:

timeToExit = true; 
CloseHandle(stdinHandle); 

und Code hängt in CloseHandle.

Der Code hängt, während das Programm von einem anderen Programm ausgeführt wird, das CreatePipe und DuplicateHandle verwendet, um die Eingabe meines Programms auf Pipe umzuleiten.

Also wie soll ich stoppen while (!timeToExit).. Thread in win32 Weg? Oder vielleicht sollte ich einige wie while (!timeToExit).. Thread ändern, um es möglich es zu stoppen?

aktualisieren ich über die Nutzung vor Aufruf von WaitForMultipleObjects gedacht ReadFile mit stdin und Ereignisse als Argument und Triggerereignis in anderem Thread, aber es gibt keine Erwähnung von anonymem Rohr wie möglich Eingang für WaitForMultipleObjects plus I versucht, wenn stdin console, verbunden und es nutzlos (immer die Steuerung ohne Verzögerung) nach dem ersten Zeichen in die Konsole eingegeben, sieht aus wie ich muss ReadConsoleInput in diesem Fall statt ReadFile?

+0

'WaitForMultipleObjects()' kann auch benannte oder unbenannte Pipes und Konsolen bedienen. – wilx

+0

@wilx 'WaitForMultipleObjects' Griffe Dinge in seltsamer Art und Weise, wenn Prozess, der mein Programm schreibt 0 Bytes ausgeführt„geleitet“stdin, es dann zurück (nach dem ersten Aufruf)' WAIT_OBJECT_0', aber 'ReadFile' kann nicht einmal 1 Byte gelesen , so komme ich zurück auf die Problemstellung in Frage, wir haben 'ReadFile' auf Eingabe warten. – fghj

+0

Schreiben Sie nicht 0 Bytes dann? – wilx

Antwort

4

Wenn Sie von der tatsächlichen STDIN einer Konsole lesen, können Sie PeekConsoleInput() und ReadConsoleInfo() anstelle von verwenden.

Wenn Sie von einer (un) benannten Pipe lesen, verwenden Sie PeekNamedPipe(), bevor Sie ReadFile() aufrufen.

Damit können Sie STDIN vor dem eigentlichen Lesen auf neue Eingaben abfragen, und dann können Sie zwischen den Umfragen den Thread-Beendigungsstatus überprüfen.

Sie können GetFileType() verwenden, um zu erkennen, welche Art von Gerät an Ihrem STD_INPUT_HANDLE-Handle angeschlossen ist.

+0

Danke, es funktioniert jetzt wie erwartet. – fghj

-2

Der sicherste Weg, dies zu tun wäre, asynchron (non-blocking) ReadFile unter Verwendung der OVERLAPPED-Struktur usw. aufzurufen. Dies kann aus Ihrem Haupt-Thread erfolgen.

Wenn/wenn Sie es abbrechen müssen, rufen Sie CancelIo (aus dem gleichen Thread, der ReadFile genannt) oder CancelIoEx (wenn aus einem anderen Thread).

Sie können möglicherweise Ihren aktuellen Ansatz arbeiten lassen; Wenn Sie timeToExit als flüchtig markieren, bleibt es möglicherweise nicht hängen, aber dieser Ansatz führt häufig zu größeren Problemen.

+2

OVERLAPPED IO funktioniert nicht für die Konsole, oder habe ich etwas verpasst? Auf der Seite CreateFile msdn gibt es beispielsweise einen speziellen Hinweis für die Konsole, welche Flags ignoriert werden, und Sie können stdin nicht mit überlappenden Flags öffnen. Kann ich etwas verpasst haben? – fghj