为啥线程在进程间通信期间会破坏命名管道?

Posted

技术标签:

【中文标题】为啥线程在进程间通信期间会破坏命名管道?【英文标题】:Why Does Threading Break Named Pipes During Inter-Processing Communications?为什么线程在进程间通信期间会破坏命名管道? 【发布时间】:2013-10-26 10:26:37 【问题描述】:

我正在尝试为命名管道流编写一个示例 C# 程序。我创建了两个可执行文件,一个用于服务器,另一个用于客户端。请在下面检查我的代码。这两个应用程序有时正常工作,有时客户端应用程序无任何原因或异常关闭,导致服务器应用程序中的 Pipe is broken 异常。我认为,在这种情况下,这些进程是不同步的,特别是当我在它们的代码中放置一些延迟时,例如调试模式延迟。为什么当服务器仍在等待 PipeDrain (pipeServer.WaitForPipeDrain()) 时,客户端进程突然关闭?

感谢您的帮助。

服务器:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Pipes;
using System.IO;
using System.Threading;

namespace NamedPipeServer

    class NamedPipeServerClass
    
        static void Main(string[] args)
        
            NamedPipeServerStream pipeServer = new NamedPipeServerStream("namedPipe", PipeDirection.InOut, 4);
            StreamReader SR = new StreamReader(pipeServer);
            StreamWriter SW = new StreamWriter(pipeServer);
            pipeServer.WaitForConnection();
            string temp;
            try
            
                SW.WriteLine("Waiting");
                SW.Flush();
                pipeServer.WaitForPipeDrain();
                temp = SR.ReadLine();
                Console.WriteLine(temp + '\n');

                SW.WriteLine("Hello");
                SW.Flush();
                pipeServer.WaitForPipeDrain();
                temp = SR.ReadLine();
                Console.WriteLine(temp + '\n');

                SW.WriteLine("How are you?");
                SW.Flush();
                pipeServer.WaitForPipeDrain();
                temp = SR.ReadLine();
                Console.WriteLine(temp + '\n');

                SW.WriteLine("GoodBye");
                SW.Flush();
                pipeServer.WaitForPipeDrain();
                temp = SR.ReadLine();
                Console.WriteLine(temp + '\n');
            

            catch (Exception ex)
            
                throw ex;
            

            finally
            
                pipeServer.WaitForPipeDrain();
                if (pipeServer.IsConnected)
                
                    pipeServer.Disconnect();
                
            

            Console.WriteLine("Server: Press any key to exit...");
            Console.ReadLine();
        
    

客户:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Pipes;
using System.IO;
using System.Threading;

namespace NamedPipeClient

    class NamedPipeClientClass
    
        static NamedPipeClientStream pipeClient;
        static StreamReader SR;
        static StreamWriter SW;
        static Thread Conversation = new Thread(new ThreadStart(Con_function));
        static bool HandShake_Ok = false;

        static void Main(string[] args)
        
            pipeClient = new NamedPipeClientStream(".", "namedPipe", PipeDirection.InOut, PipeOptions.None);
            if (pipeClient.IsConnected != true) 
             
                pipeClient.Connect(); 
            
            SR = new StreamReader(pipeClient);
            SW = new StreamWriter(pipeClient);
            Conversation.Name = "ConversationThread";
            Conversation.IsBackground = true;
            Conversation.Start();
        
        static void Con_function()
        
            string temp;
            while (true)
            
                try
                
                    temp = SR.ReadLine();
                
                catch (Exception ex)
                
                    throw ex;
                
                if (temp == "Waiting")
                
                    HandShake_Ok = true;
                    try
                    
                        SW.WriteLine("Welcome");
                        SW.Flush();
                    
                    catch (Exception ex)
                    
                        throw ex;
                    
                
                else if (HandShake_Ok && temp == "Hello")
                
                    try
                    
                        SW.WriteLine("Hi");
                        SW.Flush();
                    
                    catch (Exception ex)
                    
                        throw ex;
                    
                
                else if (HandShake_Ok && temp == "How are you?")
                
                    try
                    
                        SW.WriteLine("I am fine");
                        SW.Flush();
                    
                    catch (Exception ex)
                    
                        throw ex;
                    
                
                else if (HandShake_Ok && temp == "GoodBye")
                
                    try
                    
                        HandShake_Ok = false;
                        SW.WriteLine("Good bye :)");
                        SW.Flush();
                    
                    catch (Exception ex)
                    
                        throw ex;
                    
                
            
        
    

更新:在客户端,写入和读取管道是在一个线程中完成的,称为Conversation。如果我删除这个线程并将所有的文字和读数带入 Main 函数,问题将得到解决。为什么线程对进程间管道通信有这样的影响?

【问题讨论】:

【参考方案1】:

我相信您在这里遇到的情况是因为Conversation.IsBackground = true; 客户端应用程序不会在退出之前等待对话线程完成

试试:

Conversation.Name = "ConversationThread";
Conversation.IsBackground = true;
Conversation.Start();
Conversation.Join();

Conversation.Join(); 阻止调用线程执行,直到线程对象终止 请参阅 MSDN 上的 Thread.Join Method 和 Thread.IsBackground Property

【讨论】:

以上是关于为啥线程在进程间通信期间会破坏命名管道?的主要内容,如果未能解决你的问题,请参考以下文章

Linux进程间通信 -- 使用命名管道

进程间通信——管道

Linux进程间通信

Linux进程间通信

Linux入门进程间的通信

Linux入门进程间的通信