NamedPipeClientStream を使用するクライアントと NamedPipeServerStream を使用するサーバーがあります。
クライアントはサーバーの前に起動する可能性があり、clientStream.Connect(timeout) を呼び出すと、期待どおりに TimeoutException が発生します。
例外を防ぐために Connect を呼び出す前に NamedPipeServerStream がリッスンしているかどうかを確認する方法はありますか?
NamedPipeClientStream を使用するクライアントと NamedPipeServerStream を使用するサーバーがあります。
クライアントはサーバーの前に起動する可能性があり、clientStream.Connect(timeout) を呼び出すと、期待どおりに TimeoutException が発生します。
例外を防ぐために Connect を呼び出す前に NamedPipeServerStream がリッスンしているかどうかを確認する方法はありますか?
5年後に誰かがこの質問に出くわした場合、これが役立つかもしれません:
var isPipeRunning = Directory.GetFiles( @"\\.\pipe\" ).Contains( $"\\.\pipe\{pipeName}" )
EventWaitHandle を使用することをお勧めします。すべてのクライアントで WaitOne () を呼び出し、ストリームを開いた後にサーバーで Set () を呼び出します。
So, on "server" side, write this:
EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.ManualReset, String.Format(@"Global\{0}", "SERVER_OPENED_HANDLE"));
OpenStream (); // inside this method you would have code that opens your named pipe for incomming messages
// finally, signal that you are done
handle.Set ();
On client side, write something like this:
EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.ManualReset, String.Format(@"Global\{0}", "SERVER_OPENED_HANDLE"));
// here your thread will sleep until the server calls "Set"
handle.WaitOne ();
// then you can safelly connect to the server here
ConnectToServer ();
There remains just a few situations to handle:
1) The pipe can't be opened on server becase there is already an opened pipe with the same name (will throw an exception).
2) You successfully opened the pipe, you notified clients that you are ready but after that, a milisecond after, the server crushes from some unexpected reason and the client cannot reach the server.
3) User rights problems
In all these situations, you should handle these exceptions using a try / catch and normally, if all goes well, this code will ensure that the client will NOT try to connect before the server successfully opened the pipe.
とにかく、名前付きパイプを介して IPC を作成するためのより高度な手法を使用することをお勧めします。たとえば、WCF や .NET Remoting を使用するなどです。これは、多くの人 (私を含めないでください) によって時代遅れであると考えられているという事実に加えて、少なくとも IPC 通信には非常に適しています。 . これにより、自由とスケーラビリティが得られます (クライアントを他のマシンに常駐させる必要があり、IPC から LAN 通信、さらには WAN/インターネットに切り替える必要があるかもしれません)。
のみを使用してこれを確認する方法はありませんNamedPipeClientStream。Mutexただし、そのようなものを使用できます
// In the server
var mutex = new System.Threading.Mutex(false, "MyPipeMutex");
OpenPipeAndRunServer();
mutex.Close();
// In the client process
var mutex = new System.Threading.Mutex(false, "MyPipeMutex");
if (!mutex.WaitOne(0, false))
{
OpenPipe();
}
mutex.Close();
おそらく、Close呼び出しを try-finally ブロックでラップして、常に閉じられるようにする必要があります。クライアントでは、別のタイムアウトを使用して、NamedPipe が開かれるのを実際に待つことができます。
回避策として例外をキャッチすることもできます。