gpt4 book ai didi

c# - StreamReader.Peek 和 Thread.Interrupt 的替代品

转载 作者:行者123 更新时间:2023-11-30 18:06:43 25 4
gpt4 key购买 nike

我正在尝试做的事情的快速序言。我想启动一个进程并启动两个线程来监视 stderr 和 stdin。每个线程咀嚼流的位,然后将其发送到 NetworkStream。如果任一线程出现错误,则两个线程都需要立即死亡。

这些带有 stdout 和 stdin 监控线程的进程中的每一个都由一个主服务器进程分离出来。这变得棘手的原因是因为在任何给定时间很容易有 40 或 50 个这样的过程。只有在早上重启突发时才会有超过 50 个连接,但它确实需要能够处理 100 个或更多。我测试了 100 个同时连接。

try
{
StreamReader reader = this.myProcess.StandardOutput;

char[] buffer = new char[4096];
byte[] data;
int read;

while (reader.Peek() > -1 ) // This can block before stream is streamed to
{
read = reader.Read(buffer, 0, 4096);
data = Server.ClientEncoding.GetBytes(buffer, 0, read);
this.clientStream.Write(data, 0, data.Length); //ClientStream is a NetworkStream
}
}
catch (Exception err)
{
Utilities.ConsoleOut(string.Format("StdOut err for client {0} -- {1}", this.clientID, err));
this.ShutdownClient(true);
}

此代码块在一个当前不是后台的线程中运行。 StandardError 流有一个类似的线程。我正在使用这种方法而不是监听 OutputDataReceived 和 ErrorDataReceived,因为 Mono 中存在一个问题,导致这些事件并不总是正确触发,即使它现在似乎已修复,我喜欢这种方法确保我正在读写所有内容顺序。

带有 True 的 ShutdownClient 只是试图杀死两个线程。不幸的是,我发现使这项工作起作用的唯一方法是在 stdErrThread 和 stdOutThread 对象上使用中断。理想情况下,peek 不会阻塞,我可以只使用手动重置事件来继续检查 stdOut 或 stdIn 上的新数据,然后在事件翻转时死掉。

我怀疑这是最好的方法。有没有办法在不使用中断的情况下执行此操作?

我想更改,因为我刚刚在日志中看到我错过了 Utlities.ConsoleOut 中抛出的 ThreadInterruptException。如果静态变量为真,这只会执行 System.Console.Write,但我猜这会在某处阻塞。

编辑:

这些线程是父线程的一部分,由服务器根据请求启动。因此我无法将 StdOut 和 StdErr 线程设置为后台并终止应用程序。我可以从主服务器中终止父线程,但这又会因 Peek 阻塞而变得棘手。

添加了关于这是服务器的信息。

我也开始意识到更好的查询队列方法可能是最终的解决方案。

最佳答案

我可以说这整个困惑源于 Peek 阻塞这一事实。您实际上是在尝试修复框架中从根本上被破坏的东西,而且这绝非易事(即不是肮脏的黑客)。就个人而言,我会解决问题的根源,即阻塞 Peek。 Mono 会遵循 Microsoft 的实现,因此最终会遇到同样的问题。

虽然我确切地知道如果允许我更改框架源代码如何解决问题,但解决方法是漫长且耗时的。

但是这里是。

从本质上讲,Microsoft 需要做的是更改 Process.StartWithCreateProcess,以便为 standardOutputstandardError 都分配一个特殊类型的 StreamReader(例如 PipeStreamReader)。

在这个 PipeStreamReader 中,他们需要覆盖两个 ReadBuffer 重载(即需要首先在 StreamReader 中将两个重载更改为虚拟),这样在读取之前,调用 PeekNamedPipe 进行实际的查看。目前,FileStream.Read()(由 Peek() 调用)将在没有数据可供读取时阻塞管道读取。虽然 0 字节的 FileStream.Read() 在文件上运行良好,但在管道上运行不佳。事实上,.NET 团队遗漏了管道文档的重要部分 - PeekNamedPipe WinAPI。

The PeekNamedPipe function is similar to the ReadFile function with the following exceptions:

...

The function always returns immediately in a single-threaded application, even if there is no data in the pipe. The wait mode of a named pipe handle (blocking or nonblocking) has no effect on the function.

如果框架中没有解决这个问题,目前最好的办法是推出您自己的 Process 类(围绕 WinAPI 的薄包装器就足够了)。

关于c# - StreamReader.Peek 和 Thread.Interrupt 的替代品,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4557591/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com