我想将目录中创建的所有文件的文件信息插入数据库。如果我在目录中删除少量文件,我的程序将执行此操作,但如果我一次在目录中删除大量文件,则它不会获取所有文件(我没有进行大量测试,但它只插入了大约当我尝试一次将 800 个文件放入目录时,我的数据库中包含了 200 个名称)。
这是我的代码:
static void Main(string[] args)
{
// Create a new FileSystemWatcher and set its properties.
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = @"C:\dropDirectory";
// Add event handlers.
watcher.Created += new FileSystemEventHandler(OnChanged);
// Begin watching.
watcher.EnableRaisingEvents = true;
while(DateTime.Now.Hour < 10);
}
private static void OnChanged(object source, FileSystemEventArgs e)
{
string strInsert = "INSERT INTO Files (Filename) VALUES ('" + e.Name + "')";
string strConnection = "Server = server_name; Database = database_name; User Id = user_id; Password = password;";
using (SqlConnection con = new SqlConnection(strConnection))
{
using (SqlCommand cmd = new SqlCommand(strInsert, con))
{
con.Open();
cmd.ExecuteScalar();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我需要进行哪些更改,以便为目标目录中删除的每个文件调用我的 OnChanged 方法,无论一次删除的文件数量如何?提前致谢。
您的问题是缓冲区大小及其众所周知且有记录的问题
FileSystemWatcher使用带有一些相关标志的WinApi调用ReadDirectoryChangesW
当您第一次调用 时
ReadDirectoryChangesW,系统会分配一个缓冲区来存储更改信息。该缓冲区与目录句柄相关联,直到它被关闭,并且其大小在其生命周期内不会改变。调用此函数之间发生的目录更改将添加到缓冲区中,然后在下一次调用时返回。如果缓冲区溢出,则丢弃缓冲区的全部内容
中的类似物FileSystemWatcher是FileSystemWatcher.InternalBufferSize属性
备注您可以将缓冲区设置为 4 KB 或更大,但不得超过 64 KB。如果您尝试将 InternalBufferSize 属性设置为小于 4096 字节,您的值将被丢弃,InternalBufferSize 属性将设置为 4096 字节。为了获得最佳性能,请在基于 Intel 的计算机上使用 4 KB 的倍数。
系统通知组件文件更改,并将这些更改存储在组件创建的缓冲区中并传递给 API。每个事件最多可以使用 16 个字节的内存,不包括文件名。 如果短时间内发生多次变化,缓冲区可能会溢出。这会导致组件失去对目录中更改的跟踪,并且它只会提供全面通知。增加缓冲区的大小可以防止丢失文件系统更改事件。但是,增加缓冲区大小的成本很高,因为它来自无法换出到磁盘的非分页内存,因此请使缓冲区尽可能小。为了避免缓冲区溢出,请使用 NotifyFilter 和 IncludeSubdirectories 属性来过滤掉不需要的更改通知。
如果情况变得更糟,您可以结合使用轮询和跟踪,它已经帮助我摆脱了几次麻烦。