我正在尝试查找与Windows上的标准输出数据限制相关的信息,但在MSDN上似乎找不到这些信息。
是否存在可以写入标准输出的数据量限制?如果有,那么当达到限制时会发生什么?数据会丢失吗?
如果标准输出被重定向(例如通过从.Net启动进程并使用ProcessStartInfo.RedirectStandardOutput属性),那么这是否会影响可以写入的数据量?当我从调用进程中读取标准输出流时,这是否会影响限制?
这些限制是否与命名管道有任何关系?
这取决于它要去哪里 - 但是在.NET中重定向输出时,如果您不读取输出,可能会遇到问题。当缓冲区耗尽时,子进程中对stdout的写入将会阻塞。一个常见的死锁原因是"父"进程等待"子"进程退出,然后读取输出 - 如果子进程需要父进程读取输出来释放缓冲区空间,则此方法不起作用。
.NET通过使用Process.OutputDataReceived
和Process.ErrorDataReceived
允许事件驱动方法,从而使此过程略微简化。这意味着您不需要启动两个线程(一个用于读取stdout,另一个用于读取stderr)只是为了防止进程阻塞...
需要注意以下几点:
1) Jon是对的 - 如果缓冲区限制已达到,子进程中的写入调用将会阻塞。如果stdout流没有被重定向到可以自动排空的位置(例如文件),则需要排空stdout流。管道需要排空,通常,如果您可以“附加”到子进程的输出,则正在附加到管道。
2) 输出流的I/O 可能 是带有缓冲的,这意味着如果子进程在没有显式调用flush()
的情况下将一些信息写入stdout,您可能看不到输出。当进程退出时,将自动调用Flush,因此,如果它是一个短小的子进程,则应该没问题,但如果不是,则没有真正的方法可以强制其输出显示出来。
3) 命名管道本质上是操作系统维护的缓冲区,可以从中写入和读取 - 也就是说,它们像是一个文件,您可以从一个进程中写入并从另一个进程中读取,而实际上并没有磁盘上的文件开销。非常适用于进程间通信,但所有与缓冲/满缓冲的I/O限制仍然适用。
标准输出有一个1024字节的缓冲区
BeginOutputReadLine
和BeginErrorReadLine
来启动进程吗?我不知道 PowerShell 会有什么区别。如果这样做不起作用,我建议你用 [mcve] 提出一个新问题。 - Jon Skeet