c#FileSystemWatcher Created事件未针对所有创建的文件触发

时间:2018-10-19 04:16:47

标签: c# file-watcher

我想将目录中创建的所有文件的文件信息插入数据库。如果我在目录中放置少量文件,我的程序将执行此操作,但是如果一次在目录中放置大量文件,则无法全部获取(我没有进行大量测试,但只插入了大约当我尝试一次在目录中删除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方法?预先感谢。

1 个答案:

答案 0 :(得分:2)

您的问题是缓冲区大小,以及它众所周知且已记录的问题

FileSystemWatcher使用带有一些相关标志的ReadDirectoryChangesW WinApi 调用

  

当您首次致电ReadDirectoryChangesW时,系统会分配一个   缓冲区以存储更改信息。该缓冲区与   目录句柄,直到它关闭并且其大小不变   在其一生中。在两次调用之间发生的目录更改   该函数被添加到缓冲区,然后与下一个返回   呼叫。 如果缓冲区溢出,则缓冲区的全部内容为   丢弃

FileSystemWatcher中的类似物是FileSystemWatcher.InternalBufferSize属性

  

备注,您可以将缓冲区设置为4 KB或更大,但不能   超过64 KB。如果您尝试将InternalBufferSize属性设置为   少于4096个字节,则您的值将被丢弃,并且   InternalBufferSize属性设置为4096字节。为了最好   性能,请在基于Intel的计算机上使用4 KB的倍数。

     

系统将文件更改通知组件,并存储这些更改   组件创建的缓冲区中的更改并传递给API。 每个   事件最多可使用16个字节的内存,不包括文件名。   如果短时间内有很多更改,缓冲区可能会溢出。   这会导致组件无法跟踪目录中的更改,   而且只会提供一揽子通知。加大尺寸   缓冲区可以防止丢失文件系统更改事件。然而,   增加缓冲区大小是昂贵的,因为它来自非页面调度   无法换出到磁盘的内存,因此请保持较小的缓冲区   尽可能。 为避免缓冲区溢出,请使用NotifyFilter和   IncludeSubdirectories属性可过滤掉不需要的更改   通知

如果情况变得更糟,您可以混合使用轮询和跟踪,这使我摆脱了几次麻烦。