c# – StreamReader.Peek和Thread.Interrupt的替代方案

我正在尝试做的快速序言.我想启动一个进程并启动两个线程来监视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);
}

此代码块在一个Thread中运行,该Thread现在不是Background. StandardError流有一个类似的线程.我正在使用此方法而不是侦听OutputDataReceived和ErrorDataReceived,因为Mono中存在导致这些事件不能始终正常触发的问题,即使它现在似乎已修复,我喜欢这种方法可确保我正在阅读和编写所有内容顺序.

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

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

我想改变,因为我刚刚在我的日志中看到我错过了在Utlities.ConsoleOut中抛出的ThreadInterruptException.如果静态变量为true,这只是一个System.Console.Write,但我想这会阻塞某个地方.

编辑:

这些线程是父线程的一部分,该线程由服务器在请求时大量启动.因此,我无法将StdOut和StdErr线程设置为后台并终止应用程序.我可以从主服务器中删除父线程,但是这会再次与Peek阻塞相关.

添加了有关此服务器的信息.

此外,我开始意识到更好的查询排队方法可能是最终的解决方案.

我可以说这整个混乱源于Peek阻止的事实.你真的试图修复一些在框架中根本被破坏的东西,这绝不容易(即不是一个肮脏的黑客攻击).就个人而言,我会解决问题的根源,即阻塞Peek. Mono将遵循微软的实施,因此最终会遇到同样的问题.

虽然我知道如何解决问题,但是我应该允许更改框架源代码,但解决方法是漫长而耗时的.

但是这里.

从本质上讲,Microsoft需要做的是更改Process.StartWithCreateProcess,以便为standardOutput和standardError分配一个特殊类型的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的瘦包装就足够了).

https://stackoverflow.com/questions/4557591/alternative-to-streamreader-peek-and-thread-interrupt

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:c# – StreamReader.Peek和Thread.Interrupt的替代方案