фоновый рабочий процесс и ошибка файловой системы работают вместе - PullRequest
1 голос
/ 02 марта 2012

Привет, у меня проблема с использованием процесса Filesystemwatcher & BackgroundWorker.

У меня есть приложение Windows Form, которое проверяет наличие новых текстовых файлов в папке, обрабатывает их и создает из них XML-файлы.

Я использую FSW для мониторинга новых TXT-файлов напапка, приложение работает нормально, но когда папка получает большое количество файлов (скажем, 1000), приложение зависает, потому что обрабатывает их все.

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

Эта идея не сработала, потому что для каждого создаваемого файла я пытаюсь вызвать метод RunWorkerAsync (), поэтому, если он занят обработкой файла и пытается обработать новый, он выдаст следующую ошибку:

"Этот BackgroundWorker в настоящее время занят и не может одновременно выполнять несколько задач."

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

private void fileSystemWatcher1_Created(object sender, System.IO.FileSystemEventArgs e)
    {
        readFile();

    }

    private void readFile()
    {
        while (backgroundWorker1.IsBusy)
        {
            readFile();
        }
        backgroundWorker1.RunWorkerAsync(idx);

    }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        int i = (int)e.Argument;
        i += 1;
        e.Result = i;
    }

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        label1.Text = "Processing...";
        this.Refresh();
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        label1.Text = "Completed...";
        this.Refresh();
        idx = (int)e.Result;
    }

Выданное исключение говорит «Необработанное исключение типа« System.StackOverflowException »произошло в WindowsFormsApplication2.exe, убедитесь, что у вас нет бесконечного цикла или рекурсии»."

Конечно, я мог бы удалить ЖСБ, но я хотел бы знать, есть ли способ заставить их работать вместе, есть идеи?

Ответы [ 3 ]

2 голосов
/ 02 марта 2012

То, что у вас есть, - это классическая проблема производителя / потребителя.

Решите это с System.Collections.Concurrent.ConcurrentQueue<string>.

  • В событии FSW добавьте имя файла в очередь.
  • Запустите 1 или 2 BackgroundWorkers для обработки очереди.

И этот код спешно переполняет ваш стек:

private void readFile()
{
    while (backgroundWorker1.IsBusy)
    {
        readFile();  // the recursive call, will fail quickly
    }
    backgroundWorker1.RunWorkerAsync(idx);
}

Это не только вызывает исключение SO, но и блокирует ваш основной поток.
Вам нужен лучший способ ожидания, и ConcurrentQueue дает вам это.

1 голос
/ 02 марта 2012

Создание новых BackgroundWorkers поможет, как и решение Хенка выше.

Или вы можете сделать это, не меняя слишком много кода, просто используя ThreadPool.

    private void fileSystemWatcher1_Created(object sender, System.IO.FileSystemEventArgs e)
    {
        ThreadPool.QueueUserWorkItem(o => readFile(e));
    }


    public void readFile(System.IO.FileSystemEventArgs e)
    {
        this.BeginInvoke(new MethodInvoker(() =>
                                               {
                                                   label1.Text = "Processing...";
                                                   this.Refresh(); //you shouldn't need this
                                               }));

        //your long running read/processing... doing something event args

        this.BeginInvoke(new MethodInvoker(() =>
                                               {
                                                   label1.Text = "Completed...";
                                                   this.Refresh();
                                                   idx = (int) e.Result;
                                               }));
    }
0 голосов
/ 02 марта 2012

Почему бы не создать новый экземпляр BackgroundWorker в readFile вместо повторного использования?

...