我想将目录中创建的所有文件的文件信息插入数据库。如果我在目录中放置少量文件,我的程序将执行此操作,但是如果一次在目录中放置大量文件,则无法全部获取(我没有进行大量测试,但只插入了大约当我尝试一次在目录中删除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();
}
}
}
我需要进行哪些更改,以便无论放置在目标目录中的文件数是多少,都将为目标目录中放置的每个文件调用OnChanged方法?预先感谢。
答案 0 :(得分:2)
您的问题是缓冲区大小,以及它众所周知且已记录的问题
FileSystemWatcher
使用带有一些相关标志的ReadDirectoryChangesW
WinApi 调用
当您首次致电
ReadDirectoryChangesW
时,系统会分配一个 缓冲区以存储更改信息。该缓冲区与 目录句柄,直到它关闭并且其大小不变 在其一生中。在两次调用之间发生的目录更改 该函数被添加到缓冲区,然后与下一个返回 呼叫。 如果缓冲区溢出,则缓冲区的全部内容为 丢弃
FileSystemWatcher
中的类似物是FileSystemWatcher.InternalBufferSize
属性
备注,您可以将缓冲区设置为4 KB或更大,但不能 超过64 KB。如果您尝试将InternalBufferSize属性设置为 少于4096个字节,则您的值将被丢弃,并且 InternalBufferSize属性设置为4096字节。为了最好 性能,请在基于Intel的计算机上使用4 KB的倍数。
系统将文件更改通知组件,并存储这些更改 组件创建的缓冲区中的更改并传递给API。 每个 事件最多可使用16个字节的内存,不包括文件名。 如果短时间内有很多更改,缓冲区可能会溢出。 这会导致组件无法跟踪目录中的更改, 而且只会提供一揽子通知。加大尺寸 缓冲区可以防止丢失文件系统更改事件。然而, 增加缓冲区大小是昂贵的,因为它来自非页面调度 无法换出到磁盘的内存,因此请保持较小的缓冲区 尽可能。 为避免缓冲区溢出,请使用NotifyFilter和 IncludeSubdirectories属性可过滤掉不需要的更改 通知。
如果情况变得更糟,您可以混合使用轮询和跟踪,这使我摆脱了几次麻烦。