Named Pipe With C#

Introduction

I was working on a project that has a large amount of data that I need to transfer from one place to another. In that process I must also change the data format. That process is so lengthy, that it was taking around 19 minutes to transfer around 50K data. Then we become familiar with Named Pipes. We used that and we got a comparatively very good result.

In this article I will describe some basics of Named Pipes using one simple example. Again we are not going too deep into the theory.

Named Pipes

A Named Pipe is one-way or duplex pipe for communication between a pipe server and one or more pipe clients. All instances of a Named Pipe share the same pipe name but each instance has its own buffers and handles. Named Pipes provide shared memory for inter-process communication.

The application that creates the pipe is the pipe server and the process that connects to the pipe server is the client. Named Pipes can be used for communication between a process running on the same computer or a process running on a different computer over the Local Area Network.

Example

In this example we will have one class, employee. We will create pipes. One will fetch data from the given list and the other pipe will fetch data provided by the first and store it in another place. This is a simple console application. We are using two threads. Instead of that you can also have another console application or another process.

Process Flow

 
Main

Here we created default data and sent this data to a converter process. After the complete process we just print data to check that all the data is transferred properly.

  1. static void Main(string[] args)  
  2. {  
  3.     ResultData = new List<Client>();  
  4.     GenerateDefaultData();  
  5.   
  6.     Thread resultPipeThread = new Thread(ResultPipe);  
  7.     resultPipeThread.Start();  
  8.   
  9.     Thread converterPipeThread = new Thread(() =>ConverterPipe(DefaultData));  
  10.     converterPipeThread.Start();  
  11.     resultPipeThread.Join();  
  12.   
  13.     if (_converterStream != null)  
  14.         _converterStream.Close();  
  15.   
  16.     if (_resultStream != null)  
  17.         _resultStream.Close();  
  18.       
  19.     Console.WriteLine("ID\tName\tDefault Phone\tResult Phone");  
  20.     for (int i = 0; i < 500; i++)  
  21.     {  
  22.         Console.WriteLine(DefaultData[i].Id + "\t" + DefaultData[i].Name + "\t" + DefaultData[i].PhoneNo + "\t" + ResultData[i].PhoneNo);  
  23.     }              
  24.     Console.ReadLine();  
  25. }  
Converter Pipe

In this process, we make a change in our data and send it to the result pipe.

  1. /// <summary>  
  2. /// Process default data and send it to pipe.  
  3. /// </summary>  
  4. /// <param name="defaultData"></param>  
  5. static void ConverterPipe(List<Client> defaultData)  
  6. {  
  7.     _converterStream = new NamedPipeClientStream("MyPipeName");  
  8.     _converterStream.Connect();  
  9.       
  10.     foreach (var client in defaultData)  
  11.     {  
  12.         //changed client data  
  13.         Client newClient = new Client() { Name = client.Name, Id = client.Id, PhoneNo = "+91" + client.PhoneNo };  
  14.       
  15.         Client messageToSend = newClient;  
  16.         IFormatter formatter = new BinaryFormatter();  
  17.         formatter.Serialize(_converterStream, messageToSend);  
  18.     }  
  19.     _convertProcessCompleted = true;  
  20. }  
Result Pipe

As you can see in the following code, we get data from the converter pipe and store it to the result.

  1. /// <summary>  
  2. /// Create final result from default data.  
  3. /// </summary>  
  4. static void ResultPipe()  
  5. {  
  6.     Console.WriteLine("Waiting for connection on named pipe mypipe");  
  7.     _resultStream = new NamedPipeServerStream("MyPipeName");  
  8.     _resultStream.WaitForConnection();  
  9.   
  10.     while (_resultProcessCompleted == false)  
  11.     {  
  12.         if (_convertProcessCompleted)  
  13.         {  
  14.             _resultProcessCompleted = true;  
  15.             break;  
  16.         }  
  17.         IFormatter formatter = new BinaryFormatter();  
  18.         Client clientReceived = (Client)formatter.Deserialize(_resultStream);  
  19.         Thread.Sleep(1);  
  20.         ResultData.Add(clientReceived);  
  21.     }  
  22.     _resultStream.Close();  
  23. }  
General methods

The following are some variables, property and one simple method to generate default data for the process.

  1. static NamedPipeClientStream _converterStream;  
  2. static NamedPipeServerStream _resultStream;  
  3. static bool _convertProcessCompleted = false;  
  4. static bool _resultProcessCompleted = false;  
  5. public static List<Client> DefaultData { getset; }  
  6. public static List<Client> ResultData { getset; }  
  7.   
  8. /// <summary>  
  9. /// Generates default data to transfer.  
  10. /// </summary>  
  11. private static void GenerateDefaultData()  
  12. {  
  13.     DefaultData = new List<Client>();  
  14.     for (int i = 0; i < 500; i++)  
  15.     {  
  16.         Client client = new Client();  
  17.         client.Id = i;  
  18.         client.Name = "Client " + i.ToString();  
  19.         client.PhoneNo = "00111" + i.ToString();  
  20.         DefaultData.Add(client);  
  21.     }  
  22. }  

As I said, we are not going into detailed theory, we have seen one example. For more details about Named Pipe please check links below:

Inter-Process Communication in .NET Using Named Pipes, Part 2

Thanks.


Similar Articles