c # FileSystemWatcher Созданное событие не запускается для всех созданных файлов - PullRequest
0 голосов
/ 19 октября 2018

Я хочу вставить информацию о файле в базу данных для всех файлов, созданных в каталоге.Моя программа будет делать это, если я удаляю небольшое количество файлов в каталоге, но не получает их все, если я удаляю большие количества в каталоге сразу (я не проводил много испытаний, но он только вставил около200 имен в мою базу данных, когда я попытался сбросить 800 файлов в каталоге одновременно).

Вот мой код:

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 голосов
/ 19 октября 2018

Ваша проблема - размер буфера, и его хорошо известная и задокументированная проблема

FileSystemWatcher использует ReadDirectoryChangesW WinApi вызов с несколькими соответствующими флагами

При первом вызове ReadDirectoryChangesW система выделяет буфер для хранения информации об изменениях.Этот буфер ассоциируется с дескриптором каталога до тех пор, пока он не будет закрыт, а его размер не изменяется в течение срока службы.Изменения каталога, которые происходят между вызовами этой функции, добавляются в буфер и затем возвращаются при следующем вызове. Если переполнение буфера, все содержимое буфера отбрасывается

Аналогом FileSystemWatcher является свойство FileSystemWatcher.InternalBufferSize

Примечания Вы можете установить размер буфера 4 КБ или более, но он не должен превышать 64 КБ.Если вы попытаетесь установить для свойства InternalBufferSize менее 4096 байт, ваше значение будет отброшено, а для свойства InternalBufferSize установлено значение 4096 байт.Для лучшей производительности используйте несколько 4 КБ на компьютерах на базе Intel.

Система уведомляет компонент об изменениях файлов и сохраняет эти изменения в буфере, который компонент создает, и передает его API-интерфейсам. Каждое событие может использовать до 16 байт памяти , не включая имя файла. Если за короткое время произойдет много изменений, буфер может переполниться.Это приводит к тому, что компонент теряет отслеживание изменений в каталоге , и он будет предоставлять только общее уведомление.Увеличение размера буфера может предотвратить пропущенные события изменения файловой системы.Однако увеличение размера буфера обходится дорого, поскольку оно поступает из нестраничной памяти, которую нельзя выгрузить на диск, поэтому размер буфера должен быть как можно меньше. Чтобы избежать переполнения буфера, используйте свойства NotifyFilter и IncludeSubdirectories для фильтрации нежелательных уведомлений об изменениях .

Если хуже становится хуже, вы можете использовать сочетание опроса и отслеживания, ононесколько раз выручал меня из беды.

...