1

我有只读的命名管道,并且想阻塞直到有可用的输出(与select套接字上的行为相同)。

我假设WaitForMultipleObjects如果没有可用的输出会阻塞,但事实并非如此。为了有效地等待输出可用,可以做些什么?

在下面的代码中,循环执行了 100 次,尽管PeekNamedPipe每次迭代都返回 0 个字节可供读取。

import win32security, win32file, win32pipe, win32event, win32con

pipeName = r"\\.\pipe\test-pipe"

saAttr = win32security.SECURITY_ATTRIBUTES()

namedPipe = win32pipe.CreateNamedPipe(
    pipeName,
    win32con.PIPE_ACCESS_DUPLEX | win32con.FILE_FLAG_OVERLAPPED, # open mode
    win32con.PIPE_TYPE_BYTE, # pipe mode
    1, # max instances
    1, # out buffer size
    1, # in buffer size
    0, # timeout
    saAttr)

fileHandle = win32file.CreateFile(pipeName,
                                  win32file.GENERIC_READ,
                                  0, None,
                                  win32file.OPEN_EXISTING,
                                  0, None)

for i in range(100):
    # would expect this to block until data is available
    ret = win32event.WaitForMultipleObjects([fileHandle], 0, win32event.INFINITE)
    print(i, ret)
    size = 1

    buffer, bytesToRead, result = win32pipe.PeekNamedPipe(namedPipe, size)
    print(buffer, bytesToRead, result)
    if bytesToRead > 0:
        res = win32file.ReadFile(namedPipe, size)
4

1 回答 1

0

如果管道中有数据,我没有办法进行WaitForMultipleObjects()阻塞,而是另一种非阻塞方式来检查。令人惊讶的是win32file.GetFileSize()与命名管道一起使用。微软说它没有,但它对我有用:

import time
import win32file

pipe_path = r'\\.\pipe\asdf'

file_handle = win32file.CreateFile(pipe_path,
                                   win32file.GENERIC_READ | win32file.GENERIC_WRITE,
                                   0, None, win32file.OPEN_EXISTING, 0, None)

while True:
    if win32file.GetFileAttributes(pipe_path) != win32file.FILE_ATTRIBUTE_NORMAL:
        # pipe was closed
        break

    size = win32file.GetFileSize(file_handle)
    if size > 0:
        while size > 0:
            # pipe has data to read
            data = win32file.ReadFile(file_handle, 512)
            print('data received', data)
            size = win32file.GetFileSize(file_handle)
    else:
        time.sleep(1)

代码的效率值得商榷。您可以在这里看到它的实际效果。

关于我发现的更多指示可能是 and 的意外行为的WaitForMultipleObjects()原因WaitForSingleObject()

  • 您希望与WaitFor*()方法一起使用的文件句柄需要具有SYNCHRONIZE访问权限(MSDN 参考
    • 我不确定,但我认为这仅适用于命名管道的创建者(服务器),而不适用于消费者(客户端)。
    • 但这可能不是您问题的根源,因为创建的文件句柄CreateNamedPipe()具有SYNCHRONIZE访问权限(MSDN 参考
  • 我发现使用win32file.WaitFor*()python 包装器方法的唯一可靠来源是“Win32 上的 Python 编程”一书(在 Google Books 上)。但他们似乎在等待客户端连接,而不是等待写入管道的数据。
于 2017-04-28T10:43:05.360 回答