サーバ側のパイプ通信の実際の処理は、次の2つのメソッドで行われます。
private const string PipeName = "win7-jumplist-demopipe"; ... internal void PipeHandlerServerThread(object threadObj) { Thread currentThread = (Thread)threadObj; NamedPipeServerStream pipeServer = null; try { while (true) { pipeServer = new NamedPipeServerStream( PipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous); try { IAsyncResult async = pipeServer.BeginWaitForConnection( null, null); int index = WaitHandle.WaitAny( new WaitHandle[] { async.AsyncWaitHandle, closeApplicationEvent }); switch (index) { case 0: pipeServer.EndWaitForConnection(async); ProcessPipeCommand(pipeServer); break; case 1: // exit this thread return; default: pipeServer.Close(); break; } } catch (Exception ex) { processCommandAction("Exception: " + ex.Message); } } } finally { pipeServer.Close(); } } private void ProcessPipeCommand( NamedPipeServerStream pipeServer) { string command; using (StreamReader reader = new StreamReader(pipeServer)) using (StreamWriter writer = new StreamWriter(pipeServer)) { command = reader.ReadLine(); processCommandAction(command); writer.WriteLine("OK"); } if (pipeServer.IsConnected) { pipeServer.Disconnect(); } }
このコードはNamedPipeServerStream
クラスのインスタンスを生成し、接続を非同期に待機します。待機は、パイプ接続とアプリケーション終了イベントの両方に対して同時に行われます。どちらが先に発生するかによって、パイプスレッドがそのまま終了するか、受け取ったパイプコマンドの処理が(ProcessPipeCommand
メソッドで)開始されるかが決まります。待機は、System.Threading
名前空間に属するWaitHandle
クラスを使って行われます。
次に、クライアントアプリケーションの動作を見てみましょう。コマンドラインパラメータ付きで(つまり、ジャンプリストのタスク経由で)アプリケーションが起動されると、次のコードが実行されます。
internal static void ProcessCommandLine(string[] args) { string command = args[0]; PipeCommunications pipes = new PipeCommunications(); string result = pipes.SendCommandToServer(command); }
ここでは、同じPipeCommunications
クラスのインスタンスを生成していますが、これはクライアント側のパイプの実装なので(データはアプリケーションから既に実行中のアプリケーションインスタンスに流れる)、PipeCommunications
クラスにデリゲートを指定する必要はありません。
パイプ経由のコマンドの送信は、SendCommandToServer
メソッドで実装されます。
internal string SendCommandToServer(string command) { try { NamedPipeClientStream pipeClient = new NamedPipeClientStream( "localhost", PipeName, PipeDirection.InOut); try { using (StreamReader reader = new StreamReader(pipeClient)) using (StreamWriter writer = new StreamWriter(pipeClient)) { pipeClient.Connect(); writer.WriteLine(command); writer.Flush(); string response = reader.ReadLine(); return response; } } finally { pipeClient.Close(); } } catch (Exception ex) { System.Windows.Forms.MessageBox.Show( "Windows 7 Task Bar Demo: Pipe " + "communication failure: " + ex.Message); return null; } }
コマンドラインパラメータ(サンプルアプリケーションの場合は「Command-A」または「Command-B」)がパイプに送信され、サーバからの「OK」という応答で受信が確認されます。これが終わると、クライアントはそのまま終了します。