none
Named pipes and "The semaphore timeout period has expired" RRS feed

  • Question

  • Hello,

    I have a little problem with "named pipes" where I communicate between 2 applications. 

    In application1, I get an error all the time. Thousands of times during a 10 minute period. The error is:

    System.IO.IOException: The semaphore timeout period has expired

    The error happens for this line in "Application1" which tries to send information to "Application2".

                    //Here send information to "mainapplication"
    		  //This function is called 100 times every second from different threads
    		 _pipeClient.Send("hello", "mainPIPS", 1000); //1000 ms timeout

    So I call the function 100 times every second which should give a clue to the problem which I wonder what it is. I need to send 100 strings every second back to "Application2" asynchronously.

    The code I use is the below:

    Application1:

            private PipeClient _pipeClient;
            public Form1()
            {
                InitializeComponent();
                _pipeClient = new PipeClient();
            }
    
    
    	 //This function is called 100 times every second from different threads(asynchronous)
            void pipefunction()
            {
                try
                {
                    //Here send information to "mainapplication"		 
    		 _pipeClient.Send("hello", "mainPIPS", 1000); //1000 ms timeout
    
                }
                catch (Exception ex) { MessageBox.Show(ex.ToString());}
            }

    Application2

    //Application2 public delegate void NewMessageDelegate(string NewMessage); private PipeServer _pipeServer; public Form1() { InitializeComponent(); _pipeServer = new PipeServer(); _pipeServer.PipeMessage += new DelegateMessage(PipesMessageHandler);

                    _pipeServer.Listen("mainPIPS"); } private void PipesMessageHandler(string message) { try { if (this.InvokeRequired) { this.Invoke(new NewMessageDelegate(PipesMessageHandler), message); } else { MessageBox.Show(message); } //Get the message form other application } catch (Exception ex) { } }


    2 Classes (PipeClient and PipeServer)

    using System.IO.Pipes;
    
        class PipeClient
        {
            public void Send(string SendStr, string PipeName, int TimeOut = 1000)
            {
                try
                {
                    NamedPipeClientStream pipeStream = new NamedPipeClientStream(".", PipeName, PipeDirection.Out, PipeOptions.Asynchronous);
    
                    // The connect function will indefinitely wait for the pipe to become available
                    // If that is not acceptable specify a maximum waiting time (in ms)
                    pipeStream.Connect(TimeOut);
                    //Debug.WriteLine("[Client] Pipe connection established");
    
                    byte[] _buffer = Encoding.UTF8.GetBytes(SendStr);
                    pipeStream.BeginWrite(_buffer, 0, _buffer.Length, AsyncSend, pipeStream);
                }
                catch (TimeoutException oEX)
                {
                    //Debug.WriteLine(oEX.Message);
                }
            }
    
            private void AsyncSend(IAsyncResult iar)
            {
                try
                {
                    // Get the pipe
                    NamedPipeClientStream pipeStream = (NamedPipeClientStream)iar.AsyncState;
    
                    // End the write
                    pipeStream.EndWrite(iar);
                    pipeStream.Flush();
                    pipeStream.Close();
                    pipeStream.Dispose();
                }
                catch (Exception oEX)
                {
                    //Debug.WriteLine(oEX.Message);
                }
            }
        }
    
    /*----------------------------------------------------*/
    
        // Delegate for passing received message back to caller
        public delegate void DelegateMessage(string Reply);
        class PipeServer
        {
            public event DelegateMessage PipeMessage;
            string _pipeName;
    
            public void Listen(string PipeName)
            {
                try
                {
                    // Set to class level var so we can re-use in the async callback method
                    _pipeName = PipeName;
                    // Create the new async pipe 
                    NamedPipeServerStream pipeServer = new NamedPipeServerStream(PipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
    
                    // Wait for a connection
                    pipeServer.BeginWaitForConnection(new AsyncCallback(WaitForConnectionCallBack), pipeServer);
                }
                catch (Exception oEX)
                {
                    //Debug.WriteLine(oEX.Message);
                }
            }
    
            private void WaitForConnectionCallBack(IAsyncResult iar)
            {
                try
                {
                    // Get the pipe
                    NamedPipeServerStream pipeServer = (NamedPipeServerStream)iar.AsyncState;
                    // End waiting for the connection
                    pipeServer.EndWaitForConnection(iar);
    
                    byte[] buffer = new byte[255];
    
                    // Read the incoming message
                    pipeServer.Read(buffer, 0, 255);
                    
                    // Convert byte buffer to string
                    string stringData = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
                    //Debug.WriteLine(stringData + Environment.NewLine);
    
                    // Pass message back to calling form
                    PipeMessage.Invoke(stringData);
    
                    // Kill original sever and create new wait server
                    pipeServer.Close();
                    pipeServer = null;
                    pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
    
                    // Recursively wait for the connection again and again....
                    pipeServer.BeginWaitForConnection(new AsyncCallback(WaitForConnectionCallBack), pipeServer);
                }
                catch
                {
                    return;
                }
            }
        }




    • Edited by Silvers2 Tuesday, March 8, 2016 12:37 AM
    Tuesday, March 8, 2016 12:31 AM

Answers

  • Hi Silvers2,

    >>So I call the function 100 times every second which should give a clue to the problem which I wonder what it is. I need to send 100 strings every second back to "Application2" asynchronously.

    Here I made a demo in winfrom project and add a Timer control.

    And I set that send 100 strings every second

     public partial class Form1 : Form
        {
            private PipeClient _pipeClient;
            private int _ctr; 
    
            public Form1()
            {
                InitializeComponent();
                _pipeClient = new PipeClient();
                _ctr = 1;
            }
    
            private void cmdSend_Click(object sender, EventArgs e)
            {
                timer1.Start();
            }
    
            private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                _pipeClient = null;
            }
    
            private void timer1_Tick(object sender, EventArgs e)
            {
                for (int i = 0; i < 99; i++)
                {
                
                    _pipeClient.Send(txtMessage.Text + " - " + _ctr.ToString(), "TestPipe", 1000);
                    _ctr++;
                }
            }
        }

    My test results as below

    >>I do then understand that I should WaitForConnection but still dont exactly understand everything.

    The Servers asynchronous BeginWaitFoConnection() method is called using AsyncCallback to trigger the WaitForConnectionCallback method, which also receives the state object - in this case the original Pipe. Once into theWaitForConnectionCallback method, the passed state pipe is allocated to a local var and waiting for the connection is ended.

    For more detailed information, please check http://www.codeproject.com/Tips/492231/Csharp-Async-Named-Pipes

    Best regards,

    Kristin


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by Silvers2 Wednesday, March 9, 2016 9:22 PM
    Wednesday, March 9, 2016 7:44 AM

All replies

  • Hi Silers,

    It means the CONNECTIONTIMEOUT number of milliseconds has expired with nobody waiting for the connection on the server side.   Do you try to debug your server(i.e., some code using NamedPipeServerStream.WaitForConnection)?

    Any data written to the pipe after a NamedPipeClientStream object has connected, but before the server has called WaitForConnection, will be available to the server following the call to WaitForConnection. If it cannot solve your issue, I would suggest you provide a simplified sample about this issue to OneDrive, we'll take a further look.

    Best regards,

    Kristin


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Tuesday, March 8, 2016 9:45 AM
  • Thanks Kristin,

    Yes my code was a bit huge. I have looked at the MSDN examples you mentioned and have tried to do it from the beginning as I don't really understand what is happening in the code. So I have taken code from the MSDN. I do then understand that I should WaitForConnection but still dont exactly understand everything.

    So I then beleive I will send the message "hello" from the PipeServer to the PipeClient. I have put down the code below but I beleive I am missing something out since the messagebox doesn't show "hello" in PipeClient?

            PipeServer pipeserver = new PipeServer();
            PipeClient pipeclient = new PipeClient();
            private void button1_Click(object sender, EventArgs e)
            {
                Thread thread = new Thread(connectSERVER); thread.Start();
                thread = new Thread(connectCLIENT); thread.Start();
            }
            void connectCLIENT() { pipeclient.clientconnect(); }
            void connectSERVER() { pipeserver.serverwaitforconnection("hello"); }

    Classes

        class PipeServer
        {
            NamedPipeServerStream pipeServer = new NamedPipeServerStream("testpipe", PipeDirection.Out);
            public void serverwaitforconnection(String sendtext)
            {
                //Wait for a client to connect
                pipeServer.WaitForConnection();
                try
                {
                    //Read user input and send that to the client process.
                    using (StreamWriter sw = new StreamWriter(pipeServer))
                    {
                        sw.AutoFlush = true;
                        sw.WriteLine(sendtext);
                    }
                }
                //Catch the IOException that is raised if the pipe is broken or disconnected.
                catch (IOException e) { MessageBox.Show("ERROR: {0}", e.Message); }
            }
        }
        class PipeClient
        {
            NamedPipeClientStream pipeClient = new NamedPipeClientStream(".", "testpipe", PipeDirection.In);
            public void clientconnect()
            {
                // Connect to the pipe or wait until the pipe is available.
                if (pipeClient.IsConnected == false) { pipeClient.Connect(5000); }
               
    
                //Console.WriteLine("Connected to pipe.");
                //Console.WriteLine("There are currently {0} pipe server instances open.", pipeClient.NumberOfServerInstances);
                using (StreamReader sr = new StreamReader(pipeClient))
                {
                    string temp;
                    while ((temp = sr.ReadLine()) != null)
                    {
                        MessageBox.Show("Received from server: {0}", temp);
                    }
                }
            }
        }

    • Edited by Silvers2 Tuesday, March 8, 2016 4:05 PM
    Tuesday, March 8, 2016 3:39 PM
  • Hi Silvers2,

    >>So I call the function 100 times every second which should give a clue to the problem which I wonder what it is. I need to send 100 strings every second back to "Application2" asynchronously.

    Here I made a demo in winfrom project and add a Timer control.

    And I set that send 100 strings every second

     public partial class Form1 : Form
        {
            private PipeClient _pipeClient;
            private int _ctr; 
    
            public Form1()
            {
                InitializeComponent();
                _pipeClient = new PipeClient();
                _ctr = 1;
            }
    
            private void cmdSend_Click(object sender, EventArgs e)
            {
                timer1.Start();
            }
    
            private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                _pipeClient = null;
            }
    
            private void timer1_Tick(object sender, EventArgs e)
            {
                for (int i = 0; i < 99; i++)
                {
                
                    _pipeClient.Send(txtMessage.Text + " - " + _ctr.ToString(), "TestPipe", 1000);
                    _ctr++;
                }
            }
        }

    My test results as below

    >>I do then understand that I should WaitForConnection but still dont exactly understand everything.

    The Servers asynchronous BeginWaitFoConnection() method is called using AsyncCallback to trigger the WaitForConnectionCallback method, which also receives the state object - in this case the original Pipe. Once into theWaitForConnectionCallback method, the passed state pipe is allocated to a local var and waiting for the connection is ended.

    For more detailed information, please check http://www.codeproject.com/Tips/492231/Csharp-Async-Named-Pipes

    Best regards,

    Kristin


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by Silvers2 Wednesday, March 9, 2016 9:22 PM
    Wednesday, March 9, 2016 7:44 AM
  • Thank you Kristin,

    >> Once into theWaitForConnectionCallback method, the passed state pipe is allocated to a local var and waiting for the connection is ended.

    I beleive it seems to work now. Thank you for your effort with the demo also. As it seems the waitforconnectioncallback does the trick to wait for the connection to end.

    Thank you

    Wednesday, March 9, 2016 9:22 PM