FileSystemWacher блокирует некоторые файлы - PullRequest
0 голосов
/ 19 декабря 2018

Я использую этот код для мониторинга создания файлов в определенной папке:

        _watcher = new RecoveringFileSystemWatcher(SourceFolder, "*.xml"); 

        _watcher.Created += (_, e) =>
        {
            ProcessFile(e.Name);
        };

RecoveringFileSystemWatcher - это обертка fileSystemWatcher.Его конструктор:

    public RecoveringFileSystemWatcher (string path, string filter)
    {
        _containedFSW = new FileSystemWatcher(path, filter);
    }

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

Это метод, которыйзапускается при создании файла:

        var nfo = new FileInfo(filePath);
        if (nfo.Exists)
        {
            var archivoXml = nfo.Name;

            string archivo = String.Empty;
            try
            {
                string content = Task.Run(async () => await GetFileContent(filePath)).Result;
                if (String.IsNullOrEmpty(content))
                    return false;

                XmlDocument xml = new XmlDocument();
                xml.LoadXml(content);

                //The rest of the method
             }
         }

метод GetFileContent такой:

    private async Task<string> GetFileContent(string filePath)
    {
        string content = String.Empty;

        try
        {
            Console.Write("ONE - "); InfoLog.Save($"ONE {filePath}");
            using (StreamReader sr = new StreamReader(filePath))
            {
                Console.Write("TWO - "); InfoLog.Save($"TWO {filePath}"); 
                content = await sr.ReadToEndAsync().ConfigureAwait(false);
                Console.Write($"THREE {(sr.BaseStream == null ? "Closed" : "Opened")} - "); InfoLog.Save($"THREE {(sr.BaseStream == null ? "Closed" : "Opened")} {filePath}");
                sr.Close();
                Console.WriteLine($"FOUR {(sr.BaseStream == null ? "Closed" : "Opened")}"); InfoLog.Save($"FOUR {(sr.BaseStream == null ? "Closed" : "Opened")} {filePath}");
            }
        }
        catch (Exception ex)
        {
            InfoLog.Save($"XML file could be read -> {filePath}. See error log.");
            ErrorLog.Save(ex);
        }

        return content;
    }

Посмотрите информацию журнала, которую я пишу для отладки процесса.

Iполучил один случай с файлом с именем 1112186.xml .... это записано в журнале:

18/12/2018 19:12:10 ONE D:\GestorDocumental\Origen\1112186.xml
18/12/2018 19:12:10 XML file could not be read -> D:\GestorDocumental\Origen\1112186.xml. See error log.

Как видите, исключение выдается при использовании команды "using".

Если я вижу полный журнал, я вижу, что файл, 1112186.xml, никогда не использовался раньше, поэтому единственный шанс, что FSW сохранит файл открытым.Я не знаю почему, но кажется, что это происходит.

Также ясно, что этот процесс блокирует файл, потому что, когда я выхожу из консольного приложения, а затем снова запускаю, файл может быть обработан.

Любая помощь по этому поводу, пожалуйста?

спасибо Хайме

1 Ответ

0 голосов
/ 19 декабря 2018

Я обычно использую этот метод, чтобы проверить, заблокирован ли файл.Я получил его по одной из ссылок в stackoverflow.

  public static bool IsFileClosed(string filepath)
  {
        bool fileClosed = false;
        int retries = 20;
        const int delay = 400; // set a delay period = retries*delay milliseconds

        if (!File.Exists(filepath))
            return false;

        do
        {
            try
            {
                // Attempts to open then close the file in RW mode, denying other users to place any locks.
                FileStream fs = File.Open(filepath, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
                fs.Close();
                fileClosed = true; // success
            }
            catch (IOException) { }

            retries--;

            if (!fileClosed)
                Thread.Sleep(delay);
        }
        while (!fileClosed && retries > 0);

        return fileClosed;
    }

Это новый класс с именем FileTimerWatcher (в него будет добавлен логгер):

    public FileTimerWatcher(ILogger logger) : base(logger)
    {
        if (timer == null)
        {
            // Create a timer with a 1.5 second interval.
            // monitor the files after 1.5 seconds.
            timer = new Timer(delay);

            // Hook up the event handler for the Elapsed event.
            timer.Elapsed += new ElapsedEventHandler(ProcessFolder);

            timer.AutoReset = true;
            timer.Enabled = true;
        }
    }

    private void ProcessFolder(object sender, ElapsedEventArgs e)
    {
        var LastChecked = DateTime.Now;

        string[] files = System.IO.Directory.GetFiles(SourceDirectory, somefilter, System.IO.SearchOption.TopDirectoryOnly);

        foreach (string file in files)
        {
            ProcessFile(file); // process file here
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...