C# NamePipe使用小結


最近在一次項目中使用到了C#中命名管道,所以在此寫下一篇小結備忘。

為什么要使用命名管道呢?為了實現兩個程序之間的數據交換。假設下面一個場景。在同一台PC上,程序A與程序B需要進行數據通信,此時我們就可以使用命名管道技術來實現。命名管道的兩個對象。NamedPipeClientStream NamedPipeServerStream 對象。請求通信的一方為Client端,發送數據的一方為Server端。

使用NamedPipe來通信,如果Server端崩潰了,不會影響到客戶端。

下面我們通過一個例子來說明:

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.WriteThrough, 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) { // 通信雙方可以約定好傳輸內容的形式,例子中我們傳輸簡單文本信息。 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; })); } }

需要注意的地方:因為我們在同一台PC上面進行通信,我們只需要將 NamedPipeClientStream 構造參數中pipeServer設為"."即可。另外因為這只是一個示例,所以PipeServer中只傳遞簡單String類型。當然也可以傳遞其他類型的內容。

運行效果:

感謝您的閱讀!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM