ReadDirectoryChangesW似乎丢失事件

问题描述:

我一直在试图让ReadDirectoryChangesW监视文件更改的子树,但我发现我得到不一致的结果。以下是一个说明问题的自包含测试案例。当我运行这一点,有时会产生:ReadDirectoryChangesW似乎丢失事件

A : Created 
C : Updated 
A : Deleted 

还有一次,它可能会产生:

A : Created 
B : Updated 
C : Updated 
A : Deleted 

我创造了巨大的缓冲区,被改变的文件的数量非常少(3个文件)。

代码:

import os, sys, time, threading 
import win32file, win32event, win32con, pywintypes 

class ChangeFiles (threading.Thread) : 
    def run(self) : 
     files = [ 'A', 'B', 'C' ] 
     time.sleep(1) 
     for path in files : f = open(path, 'w'); f.write('mooo'); f.close() 
     time.sleep(0.5) 
     for path in files : os.remove(path) 

ChangeFiles().start() 

FILE_LIST_DIRECTORY = 0x0001 

handle = win32file.CreateFile (
    '.', 
    FILE_LIST_DIRECTORY, 
    win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE | win32con.FILE_SHARE_DELETE, 
    None, 
    win32con.OPEN_EXISTING, 
    win32con.FILE_FLAG_BACKUP_SEMANTICS | win32file.FILE_FLAG_OVERLAPPED, 
    None 
) 

buffer = win32file.AllocateReadBuffer(1024 * 64) 
overlapped = pywintypes.OVERLAPPED() 
overlapped.hEvent = win32event.CreateEvent(None, 0, 0, None) 

readFlags = win32con.FILE_NOTIFY_CHANGE_FILE_NAME | \ 
      win32con.FILE_NOTIFY_CHANGE_DIR_NAME | \ 
      win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES | \ 
      win32con.FILE_NOTIFY_CHANGE_SIZE  | \ 
      win32con.FILE_NOTIFY_CHANGE_LAST_WRITE | \ 
      win32con.FILE_NOTIFY_CHANGE_SECURITY 

ACTIONS = { 1 : "Created", 2 : "Deleted", 3 : "Updated" } 

while 1 : 
    win32file.ReadDirectoryChangesW(handle, buffer, False, readFlags, overlapped) 

    rc = win32event.WaitForSingleObject(overlapped.hEvent, 200) 

    if rc == win32event.WAIT_OBJECT_0 : 
     nbytes = win32file.GetOverlappedResult(handle, overlapped, True) 
     if nbytes > 0 : 
      for action, file in win32file.FILE_NOTIFY_INFORMATION(buffer, nbytes) : 
       print '%s : %s' % (file, ACTIONS.get (action, "Unknown")) 
     else : 
      print 'no bytes' 
      break 
    elif rc < 0 : 
     print 'Error: %d' % win32api.GetLastError() 
     break 
+0

我开始猜测这是一种情况,如果一棵树落在森林里,并且周围没有人听到它,它是否还会发出声音?在这种情况下,如果没有未完成的对ReadDirectoryChangesW的调用,并且文件系统发生更改,您是否稍后将了解有关更改?也许不是。我一直在使用一个叫做看门狗的python库,它似乎在为我工作,但我仍然想知道为什么我上面的代码示例错过了事件。 –

+1

根据[文档](http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465%28v=vs.85%29.aspx),在调用此函数之间发生_Directory更改被添加到缓冲区,然后在下一次呼叫时返回。因此,事件应该被缓冲,直到下一次呼叫。我从来没有使用Python,但我没有在本机代码中使用此API的任何问题。 – Luke

这里的问题是,你传递给WaitForSingleObject超时是非常低的,所以功能趋于你收到通知的事件之前超时。您的代码不检查该情况,因此您看不到任何输出(请尝试测试rc > 0)。

您可以通过将INFINITE(即0xFFFFFFFF)的值传递给WaitForObject来解决此问题。