在c#中使用命名管道在两个进程之间进行双工操作

Posted

技术标签:

【中文标题】在c#中使用命名管道在两个进程之间进行双工操作【英文标题】:duplex operation between two processes using named pipes in c# 【发布时间】:2013-01-27 19:08:58 【问题描述】:

我正在尝试使用命名管道在同一台机器上的服务器和客户端进程之间进行通信。服务器向客户端发送消息,客户端对其进行处理并返回结果,服务器应该得到结果。

这是服务器的代码:

using System;
using System.IO;
using System.IO.Pipes;

class PipeServer

    static void Main()
    
        using (NamedPipeServerStream pipeServer =
            new NamedPipeServerStream("testpipe", PipeDirection.InOut))
        
            Console.WriteLine("NamedPipeServerStream object created.");

            // Wait for a client to connect
            Console.Write("Waiting for client connection...");
            pipeServer.WaitForConnection();

            Console.WriteLine("Client connected.");
            try
            
                // Read user input and send that to the client process.
                using (StreamWriter sw = new StreamWriter(pipeServer))
                
                    sw.AutoFlush = true;
                    Console.Write("Enter text: ");
                    sw.WriteLine(Console.ReadLine());
                

                pipeServer.WaitForPipeDrain();

                using (StreamReader sr = new StreamReader(pipeServer))
                
                    // Display the read text to the console 
                    string temp;

                    // Wait for result from the client. 
                    while ((temp = sr.ReadLine()) != null)
                    
                        Console.WriteLine("[CLIENT] Echo: " + temp);
                    
                

            
            // Catch the IOException that is raised if the pipe is 
            // broken or disconnected.
            catch (IOException e)
            
                Console.WriteLine("ERROR: 0", e.Message);
            
        
    

这是客户端的代码:

using System;
using System.IO;
using System.IO.Pipes;

class PipeClient

    static void Main(string[] args)
    
        using (NamedPipeClientStream pipeClient =
            new NamedPipeClientStream(".", "testpipe", PipeDirection.InOut))
        

            // Connect to the pipe or wait until the pipe is available.
            Console.Write("Attempting to connect to pipe...");
            pipeClient.Connect();

            Console.WriteLine("Connected to pipe.");
            Console.WriteLine("There are currently 0 pipe server instances open.",
               pipeClient.NumberOfServerInstances);
            using (StreamReader sr = new StreamReader(pipeClient))
            
                // Display the read text to the console
                string temp;
                while ((temp = sr.ReadLine()) != null)
                
                    Console.WriteLine("Received from server: 0", temp);
                
            


            // send the "result" back to the Parent process.
            using (StreamWriter sw = new StreamWriter(pipeClient))
            
                sw.AutoFlush = true;
                sw.WriteLine("Result");
            

            pipeClient.WaitForPipeDrain();

        
        Console.Write("Press Enter to continue...");
        Console.ReadLine();
    

但是在服务器代码中,就行 pipeServer.WaitForPipeDrain();我收到一个 ObjectDisposedException,它说“无法访问封闭的管道”。

在将 sw.AutoFlush 设置为 true 时,我在客户端代码中也遇到了同样的错误。

基本上我在 c# 中找不到双工命名管道的示例。我要么需要它,要么需要一个匿名管道的示例,其中有两个管道,一个用于读取,一个用于在父进程和子进程之间写入。

提前致谢。

【问题讨论】:

不处理StreamWriter 也关闭底层流(即你的pipeServer)? 在命名管道上运行的 WCF 将为您节省大量工作。 请问在哪里可以看到示例? 如果其他人对此有疑问,请尝试删除所有使用块(即,仅 StreamWriter sw = new StreamWriter(pipeClient);) - 这对我有用,我认为垃圾收集器会正确处理当我关闭应用程序时进行处置。 【参考方案1】:

问题是 StreamWriter 的 using 块,它将关闭底层 Stream(这是您的管道)。如果您不使用该块,它应该可以工作。

您可以执行以下操作:

using (var pipeServer = new NamedPipeServerStream("testpipe", PipeDirection.InOut))
using (var streamReader = new StreamReader(pipeServer))
using (var streamWriter = new StreamWriter(pipeServer))

   // ... Your code ..

正如 Johannes Egger 所指出的,StreamWriter 会刷新 Dispose() 上的流,因此应该首先处置 StreamWriter,从而成为要处置的最内层对象。

【讨论】:

谢谢,这解决了问题。代码中还有一个问题,读取发生在 while 循环中,结果出现死锁,将 while 更改为 If,现在可以正常工作了。 在我的情况下,写入器在读取器之后被处理很重要,因为写入器在处理时进行了刷新,但是当读取器首先被处理时,管道也被处理并且写入器不能冲洗。

以上是关于在c#中使用命名管道在两个进程之间进行双工操作的主要内容,如果未能解决你的问题,请参考以下文章

swoole进程间如何通信

使用命名管道在两个进程之间发送字符串

C# 和 Python 之间的命名管道

C#的命名管道(named pipe)

C# 和 python 之间的命名管道

为啥命名管道是本地的?