请问为什么NamedPipeClientStream.Connect()会抛出System.IO.FileNotFoundException异常(无法找到指定的文件)?我以为Connect()方法只会永远阻塞而不会抛出异常。
谢谢您提前的帮助!
请问为什么NamedPipeClientStream.Connect()会抛出System.IO.FileNotFoundException异常(无法找到指定的文件)?我以为Connect()方法只会永远阻塞而不会抛出异常。
谢谢您提前的帮助!
NamedPipeClientStream.Connect()
是对 WaitNamedPipe
和 CreateFile
内核方法的托管封装。
更多信息请参见: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365800(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx
托管部分的代码如下(简化):
public void Connect(int timeout = -1) {
int tickCount = Environment.TickCount;
int elapsed = 0;
SafePipeHandle safePipeHandle;
while (true) {
if (!WaitNamedPipe(normalizedPipePath, timeout - elapsed)) {
int lastWin32Error = Marshal.GetLastWin32Error();
if (lastWin32Error != FILE_NOT_FOUND && lastWin32Error != SUCCESS) {
ThrowWinIOError(lastWin32Error, string.Empty);
}
}
if (timeout != -1 && (elapsed = Environment.TickCount - tickCount) >= timeout) {
throw new TimeoutException();
}
safePipeHandle = CreateFile(normalizedPipePath, m_access, FileShare.None, null, FileMode.Open, num, null);
if (!safePipeHandle.IsInvalid) {
// success
return;
}
int lastWin32Error2 = Marshal.GetLastWin32Error();
if (lastWin32Error2 == PIPE_BUSY) {
continue;
}
ThrowWinIOError(lastWin32Error2, string.Empty);
}
}
WaitNamedPipe
,如果管道不存在则立即返回,并且托管代码进行重试(如果未指定超时,则无限重试)。棘手的部分在于CreateFile
不处理FILE_NOT_FOUND错误(仅处理PIPE_BUSY错误)-我怀疑这是您可能遇到竞争条件的地方。WaitNamedPipe
返回ok,但在命中CreateFile
之前,管道发生了更改(从休眠后返回空?),并且CreateFile
引发了您看到的异常。Connect
方法包装到重试FILE_NOT_FOUND IOException
上。