5

我有一个使用 NamedPipeClientStream 的客户端和一个使用 NamedPipeServerStream 的服务器。

客户端可能在服务器之前启动,当它调用 clientStream.Connect(timeout) 时,我得到了预期的 TimeoutException。

有什么方法可以在调用 Connect 之前检查是否有 NamedPipeServerStream 监听以防止异常?

4

3 回答 3

4

如果五年后有人碰到这个问题,这可能会有所帮助:

var isPipeRunning = Directory.GetFiles( @"\\.\pipe\" ).Contains( $"\\.\pipe\{pipeName}" )
于 2020-09-04T10:05:43.023 回答
2

我建议你应该使用 EventWaitHandle。在所有客户端上,调用 WaitOne(),在服务器上打开流后,调用 Set()。

所以,在“服务器”端,这样写:

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 ();

在客户端,编写如下内容:

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 ();

剩下的只有几种情况需要处理:

1)无法在服务器上打开管道,因为已经有一个同名的打开管道(将抛出异常)。

2)您成功打开管道,通知客户端您已准备好,但在那之后,一毫秒后,服务器因某种意外原因崩溃,客户端无法访问服务器。

3) 用户权限问题

在所有这些情况下,您应该使用 try/catch 处理这些异常,通常,如果一切顺利,此代码将确保客户端在服务器成功打开管道之前不会尝试连接。

无论如何,我建议使用更先进的技术通过命名管道制作 IPC,例如使用 WCF 甚至 .NET Remoting,除了它在某种程度上被许多人(不包括我)认为已经过时的事实至少对于 IPC 通信来说是非常不错的. 这将为您提供自由和可扩展性(也许有一天您将需要您的客户端能够驻留在其他机器上,并且您将不得不从 IPC 切换到 LAN 通信甚至是 WAN / Internet)。

于 2015-08-06T06:23:49.413 回答
2

无法仅使用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。

您还可以捕获异常作为解决方法。

于 2015-08-06T06:47:12.870 回答