C # NamePipe usage Summary
The named pipeline in C # was recently used in a project, so I will write a summary here. Why use a named pipe? To exchange data between two programs. Assume that the following scenario is used. On the same PC, program A and program B need to communicate with each other. In this case, we can use the named pipeline technology. Name the two objects of the MPs queue. NamedPipeClientStream and NamedPipeServerStream objects. The Client side of the Request communication, and the Server side of the sent data. Use NamedPipe for communication. If the Server crashes, the client will not be affected. The following is an example: Server: UI:
<Grid> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <TextBlock Text="Received Message:" Grid.Row="1" Margin="10"/> <TextBlock x:Name="tblRecMsg" VerticalAlignment="Center" Grid.Row="1" Grid.Column="1"/> <Button Content="Send" Grid.Row="2" Margin="10" Click="OnSend"/> <TextBox x:Name="txtSendMsg" VerticalAlignment="Center" Grid.Row="2" Grid.Column="1" Margin="10"/> </Grid>
Code:
Private NamedPipeServerStream _ pipe; private const string PipeName = "PipeSample"; private const int PipeInBufferSize = 4096; private const int PipeOutBufferSize = 65535; private Encoding encoding = Encoding. UTF8; public MainWindow () {InitializeComponent (); _ pipe = new NamedPipeServerStream (PipeName, PipeDirection. inOut, 1, PipeTransmissionMode. message, PipeOptions. asynchronous | PipeOptions. wri TeThrough, PipeInBufferSize, PipeOutBufferSize); _ pipe. beginWaitForConnection (WaitForConnectionCallback, _ pipe);} private void WaitForConnectionCallback (IAsyncResult ar) {var pipeServer = (NamedPipeServerStream) ar. asyncState; pipeServer. endWaitForConnection (ar); var data = new byte [PipeInBufferSize]; var count = pipeServer. read (data, 0, PipeInBufferSize); if (count> 0) {// both parties can agree on the form of the transmitted content. For example: We transmit simple text information. String message = encoding. getString (data, 0, count); Dispatcher. beginInvoke (new Action () => {tblRecMsg. text = message;}) ;}} private void OnSend (object sender, RoutedEventArgs e) {if (_ pipe. isConnected) {try {string message = txtSendMsg. text; byte [] data = encoding. getBytes (message); _ pipe. write (data, 0, data. length); _ pipe. flush (); _ pipe. waitForPipeDrain ();} catch {}} Close ();}
Client: UI:
<Grid> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Button Content="Connect" Margin="10" Click="OnConnect"/> <TextBlock Text="Received Message:" Grid.Row="1" Margin="10"/> <TextBlock x:Name="tblRecMsg" Grid.Row="1" Grid.Column="1"/> </Grid>
Code:
private const string PipeServerName = "PipeServer.exe"; private const string PipeName = "PipeSample"; private Encoding encoding = Encoding.UTF8; private NamedPipeClientStream _pipe; private bool _starting = false; public MainWindow() { InitializeComponent(); } private void OnConnect(object sender, RoutedEventArgs e) { if (_starting) { return; } var path = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, PipeServerName); var startInfo = new ProcessStartInfo(path) { UseShellExecute = false, CreateNoWindow = true }; try { var process = Process.Start(startInfo); _pipe = new NamedPipeClientStream ( ".", PipeName, PipeDirection.InOut, PipeOptions.Asynchronous | PipeOptions.WriteThrough ); _pipe.Connect(); _pipe.ReadMode = PipeTransmissionMode.Message; string message = "Connected!"; byte[] data = encoding.GetBytes(message); _pipe.BeginWrite(data, 0, data.Length, PipeWriteCallback, _pipe); _starting = true; } catch (Exception ex) { Debug.Write(ex.StackTrace); } } private void PipeWriteCallback(IAsyncResult ar) { var pipe = (NamedPipeClientStream)ar.AsyncState; pipe.EndWrite(ar); pipe.Flush(); pipe.WaitForPipeDrain(); var data = new byte[65535]; var count = pipe.Read(data, 0, data.Length); if (count > 0) { string message = encoding.GetString(data, 0, count); Dispatcher.BeginInvoke(new Action(() => { tblRecMsg.Text = message; })); } }
Note: Because we communicate on the same PC, we only need to set the pipeServer to "." In the NamedPipeClientStream constructor. In addition, because this is only an example, only the simple String type is passed in PipeServer. Of course, other types of content can also be passed.