NamedPipeClientStream.Connect() 抛出 System.IO.FileNotFoundException: 无法找到指定的文件。

5

请问为什么NamedPipeClientStream.Connect()会抛出System.IO.FileNotFoundException异常(无法找到指定的文件)?我以为Connect()方法只会永远阻塞而不会抛出异常。

谢谢您提前的帮助!

1个回答

2
NamedPipeClientStream.Connect() 是对 WaitNamedPipeCreateFile 内核方法的托管封装。

更多信息请参见: 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上。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接