中堅プログラマーの備忘録

忘れっぽくなってきたので備忘録として・・・

【C#.net】名前付きパイプで非同期のプロセス間通信をする

1.概要

同じPC内でのプロセス間通信を名前付きパイプでやってみようと思います。
1対1のプロセス間通信なら匿名パイプでこと足りますが
なんせ匿名パイプは親子関係が必要になり使い勝手が悪いです。


ソケット通信でもいいのですが、ローカルのプロセス間通信
に対してオーバースペックなような気がしますので、ここでは採用しません。


WCF(Windows Communication Foundation)でのプロセス間通信については
また別途記事にしたいと思います。


今回はあくまで簡易的にプロセス間通信を実装することを目的としています。


2.サーバー側

Formアプリケーションで作成しています。
【WaitForConnectionAsync】メソッドを使用するため
.net flameworkのバージョンを4.6にしています。

using System;
using System.IO;
using System.IO.Pipes;
using System.Windows.Forms;

namespace NamePipeServer
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private async void ServerStart()
        {
            // 繰り返す
            while (true)
            {
                using (var pipeServer = new NamedPipeServerStream("testpipe"))
                {
                    // クライアントからの接続待ち
                    await pipeServer.WaitForConnectionAsync();

                    // メッセージを受信(読み込み)
                    using (var reader = new StreamReader(pipeServer))
                    {
                        var message = await reader.ReadLineAsync();
                        Console.WriteLine($"Received: {message}");
                    }
                }
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            ServerStart();
        }
    }
}

2.クライアント側

Formアプリケーションで作成しています。
Buttonコントロールを使用しています。
【ConnectAsync】メソッドを使用するため
.net flameworkのバージョンを4.6にしています。

using System;
using System.IO;
using System.IO.Pipes;
using System.Windows.Forms;

namespace NamePipeClient
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Client();
        }

        private async void Client()
        {
            using (var pipeClient = new NamedPipeClientStream("testpipe"))
            {
                try
                {
                    // サーバに接続(5秒タイムアウト)
                    await pipeClient.ConnectAsync(5000);

                    // メッセージを送信(書き込み)
                    using (var writer = new StreamWriter(pipeClient))
                    {
                        var message = "test";
                        
                        await writer.WriteLineAsync(message);
                        Console.WriteLine($"Sent: {message}");
                    }
                }
                catch (TimeoutException ex)
                {
                    // タイムアウト時の処理
                    Console.WriteLine($"TimeOut: {ex.Message}");
                }
                catch (Exception ex)
                {
                    // その他のエラー
                    Console.WriteLine($"Error: {ex.Message}");
                }
            }
        }
    }
}

4.動作

クライアント側のボタンをクリックするとプロセス間通信が開始されます。
サーバーはプロセス間通信が終わると【testpipe】を破棄しますが
再度pipeを作成し、クライアントからの通信を待ちます。


クライアント側のボタンをクリックし続けると
その都度プロセス間通信が行われます。


非常に簡単に名前付きパイプによるプロセス間通信が実装出来ました。