NamedPipeClientStream.Connect()抛出System.IO.FileNotFoundExcep

本文关键字:System IO FileNotFoundExcep 抛出 Connect NamedPipeClientStream | 更新日期: 2023-09-27 18:01:36

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

提前感谢!

NamedPipeClientStream.Connect()抛出System.IO.FileNotFoundExcep

NamedPipeClientStream.Connect()只是WaitNamedPipeCreateFile内核方法的托管包装。

更多:https://msdn.microsoft.com/en-us/library/windows/desktop/aa365800 (v = vs.85) . aspxhttps://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被击中之前,管道发生了变化(休眠后返回void ?), CreateFile抛出异常,你看到了。

解决方法应该相对简单-包装Connect方法以重试FILE_NOT_FOUND IOException