我一直在尝试让 ReadDirectoryChangesW 监视子树的文件更改,但我发现得到的结果不一致。以下是一个说明问题的独立测试用例。当我运行它时,它有时会产生:
A : Created
C : Updated
A : Deleted
Run Code Online (Sandbox Code Playgroud)
另一次它可能会产生:
A : Created
B : Updated
C : Updated
A : Deleted
Run Code Online (Sandbox Code Playgroud)
我创建了一个巨大的缓冲区,并且正在更改的文件数量非常小(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 …Run Code Online (Sandbox Code Playgroud) 我正在编写一个小应用程序,用于监视某个目录中是否有新添加的文件。
我想将监控代码放在一个单独的线程中,这样我就可以让主线程自由用于其他事情,并在需要时取消监控线程。
我能够正确地编写所有内容,除了一件事:
我无法正确退出监控线程,因此发表了这篇文章。
我在主线程中发出一个事件对象信号,等待线程退出,然后进行清理。
问题在于我的使用,ReadDirectoryChangesW因为在我注释掉那段代码后一切正常。
一旦事件句柄发出信号,ReadDirectoryChangesW就会阻塞线程,防止它“捕获”事件并退出。如果我在目录中添加一个新文件,它会“解锁” ReadDirectoryChangesW,线程“捕获”事件并退出。
为了进一步提供帮助,我在下面制作了一个小型MVCE,它说明了我到目前为止所说的内容。
#include <iostream>
#include <Windows.h>
#include <map>
struct SThreadParams
{
HANDLE hEvent;
HANDLE hDir;
int processDirectoryChanges(const char *buffer)
{
if (NULL == buffer) return -1;
DWORD offset = 0;
char fileName[MAX_PATH] = "";
FILE_NOTIFY_INFORMATION *fni = NULL;
do
{
fni = (FILE_NOTIFY_INFORMATION*)(&buffer[offset]);
// since we do not use UNICODE,
// …Run Code Online (Sandbox Code Playgroud) c++ winapi multithreading asynchronous readdirectorychangesw
我已经阅读了文档ReadDirectoryChangesW(),也看过了CDirectoryChangeWatcher项目,但都没有说出为什么人们想要异步调用它.我理解当前线程不会阻塞,但是,至少对于使用完成端口的CDirectoryChangeWatcher代码,当它调用时 GetQueuedCompletionStatus(),该线程无论如何都会阻塞(如果没有更改).
因此,如果我ReadDirectoryChangesW()首先在一个单独的线程中同步调用我不关心它是否阻塞,为什么我会想要ReadDirectoryChangesW()异步调用?
我尝试监视目录树的内容,其中包含大量文件(例如,许多目录每个目录有 9000 个文件)。
同步模式:
我首先尝试在阻塞模式(同步)下使用ReadDirectoryChangesW,但是当我删除监视的目录时,我最终陷入死锁,我无法检测也无法退出。
#
# Monitors a directory for changes and pass the changes to the queue
#
def MonitorDirectory(self, out_queue):
print("Monitoring instance \'{0}\' is watching directory: {1}".format(self.name, self.path))
# File monitor
FILE_LIST_DIRECTORY = 0x0001
buffer = win32file.AllocateReadBuffer(1024 * 64)
hDir = win32file.CreateFile(self.path,
FILE_LIST_DIRECTORY,
win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE | win32con.FILE_SHARE_DELETE,
None,
win32con.OPEN_EXISTING,
win32con.FILE_FLAG_BACKUP_SEMANTICS,
None)
# Monitor directory for changes
while not self._shutdown.is_set():
# Create handle to directory if missing
#if os.path.isdir(self.path):
self.fh.write("ReOpen Exists {0}\n".format(os.path.isdir(self.path)))
self.fh.flush()
try:
hDir …Run Code Online (Sandbox Code Playgroud) python multithreading readdirectorychangesw pywin32 python-3.x
我正在尝试在循环中异步使用ReadDirectoryChangesW。
下面的片段说明了我想要实现的目标:
DWORD example()
{
DWORD error = 0;
OVERLAPPED ovl = { 0 };
ovl.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
if (NULL == ovl.hEvent) return ::GetLastError();
char buffer[1024];
while(1)
{
process_list_of_existing_files();
error = ::ReadDirectoryChangesW(
m_hDirectory, // I have added FILE_FLAG_OVERLAPPED in CreateFile
buffer, sizeof(buffer), FALSE,
FILE_NOTIFY_CHANGE_FILE_NAME,
NULL, &ovl, NULL);
// we have new files, append them to the list
if(error) append_new_files_to_the_list(buffer);
// just continue with the loop
else if(::GetLastError() == ERROR_IO_PENDING) continue;
// RDCW error, this …Run Code Online (Sandbox Code Playgroud) 我正在尝试e:\test使用ReadDirectoryChangesW API 监视目录.
我的代码:
#define UNICODE
#define WIN32_WINNT 0x0500
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
HANDLE hDir;
int _tmain(int argc, _TCHAR* argv[])
{
FILE_NOTIFY_INFORMATION fniDir;
DWORD i = 0;
hDir = CreateFile(_T("e:\\test"), GENERIC_READ , FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
ReadDirectoryChangesW(hDir, &fniDir, sizeof(fniDir), TRUE, FILE_NOTIFY_CHANGE_FILE_NAME, &i, NULL, NULL);
while(TRUE)
{
if(i>0)
wprintf(L"%s", fniDir.FileName);
}
CloseHandle(hDir);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我不知道我的代码有什么问题,因为我还没有完全理解ReadDirectoryChangesW文档,特别是LPOVERLAPPED 参数.
当我运行代码时,我没有得到任何输出,除了一个空白的控制台窗口.有人能指出我正确的方向吗?
谢谢.
c winapi filenames readdirectorychangesw systems-programming
winapi ×4
asynchronous ×2
c++ ×2
python ×2
windows ×2
c ×1
filenames ×1
python-3.x ×1
pywin32 ×1