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
答
这里的问题是,你传递给WaitForSingleObject
超时是非常低的,所以功能趋于你收到通知的事件之前超时。您的代码不检查该情况,因此您看不到任何输出(请尝试测试rc > 0
)。
您可以通过将INFINITE
(即0xFFFFFFFF)的值传递给WaitForObject
来解决此问题。
我开始猜测这是一种情况,如果一棵树落在森林里,并且周围没有人听到它,它是否还会发出声音?在这种情况下,如果没有未完成的对ReadDirectoryChangesW的调用,并且文件系统发生更改,您是否稍后将了解有关更改?也许不是。我一直在使用一个叫做看门狗的python库,它似乎在为我工作,但我仍然想知道为什么我上面的代码示例错过了事件。 –
根据[文档](http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465%28v=vs.85%29.aspx),在调用此函数之间发生_Directory更改被添加到缓冲区,然后在下一次呼叫时返回。因此,事件应该被缓冲,直到下一次呼叫。我从来没有使用Python,但我没有在本机代码中使用此API的任何问题。 – Luke