サーバ側のパイプ通信の実際の処理は、次の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」という応答で受信が確認されます。これが終わると、クライアントはそのまま終了します。
