在Windows中,即使没有待处理的输入,如何强制C的fread返回?

时间:2018-10-30 22:07:48

标签: c winapi stdin eof fread

在具有两个线程的Windows程序中:thread1thread2

当呼叫thread1中的fread(buffer, 1, 10, stdin)被阻止等待输入时,是否可以执行thread2来强制fread返回?

到目前为止,我尝试从fclose(stdin)调用thread2,但似乎不起作用。程序将停留在fclose调用中,直到stdin流中有一些输入可用为止。

我要实现的目的是优雅地终止thread1而不是仅仅用TerminateThread终止它,因为最后thread1要做一些工作。

要考虑的另一件事是stdin是命名管道的一端。我无法控制管道另一端的程序。
我需要的只是断开程序与管道的连接(在这种情况下为stdin)。

2 个答案:

答案 0 :(得分:5)

致电fclose(stdin)是一个非常糟糕的主意;如果它发生在fread之前(未按顺序排序),或者调用fread的线程对stdin进行了其他操作,则将导致未定义的行为fread返回,并且它不会解除对fread的阻止,因为fclose在获得stdin上的锁定之前无法进行,正在进行的fread排除在外

stdio根本上不适合您要在此处执行的操作。您可以通过第二个管道进行转发来修补它,而另一个线程将从stdin中读取并写入新管道。然后,您可以通过关闭管道的写入端来中止管道的读取端上的fread。多余的线程仍然会卡住,但是无论如何您都将终止并没有关系。另外(可能更干净),您可以使用文件描述符(或Windows文件句柄)代替stdio和poll(或Windows等效文件)来确定是否有要读取的输入。您可以结合使用这些方法,以将Windows特定的文件处理逻辑放在额外的线程中(从而能够干净地终止它),并继续在程序逻辑线程中使用可移植的stdio

答案 1 :(得分:2)

如果您不能使用CancelSynchronousIo,则可以使用CloseHandle关闭基础文件句柄,如下所示:

CloseHandle((HANDLE)_get_osfhandle(_fileno(stdin))) ;

这应该导致fread返回。