Индикатор выполнения BackgroundWorker не работает - PullRequest
0 голосов
/ 09 мая 2018

Индикатор выполнения BackgroundWorker не обновляется при выполнении некоторых задач. То, чего я хотел бы достичь, - это перемещение индикатора выполнения во время итерации каждого файла в DirectoryInfo. Предположим, у нас есть 20 файлов «.sql», в то время как первый файл заполнен, он должен быть 5%, 10% и т. Д. Вот мой код.

private void CSV_Click(object sender, RoutedEventArgs e)
        {         
            try
            {
                btnExtract.IsEnabled = false;
                workerextract.RunWorkerAsync();

        }
        catch (Exception ex)
        {
            System.Windows.MessageBox.Show(ex.Message);
        }
    }

    private void workerextract_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
    {
        try
        {
           this.Dispatcher.Invoke(() =>
            {

                DirectoryInfo di = new DirectoryInfo(txtQueryfolder.Text);
                files = di.GetFiles("*.sql").Count();
                currentfile = 0;

                foreach (FileInfo fi in di.GetFiles("*.sql"))
                {
                    // Open the text file using a stream reader.
                    using (StreamReader sr = new StreamReader(fi.FullName))
                    {
                        // Read the stream to a string, and write the string to the console.
                        string line = sr.ReadToEnd();

                        //System.Windows.MessageBox.Show(line);
                        ExtractToCSV(line, System.IO.Path.GetFileNameWithoutExtension(fi.Name));
                        currentfile++;
                    }
                    int percentage = (currentfile + 1) * 100 / files;
                    workerextract.ReportProgress(percentage);
                }

            });

        }
        catch(Exception ex)
        {
            System.Windows.MessageBox.Show(ex.Message);
        }
    }

    private void workerextract_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
    {
        progressBarExtract.Value = e.ProgressPercentage;
    }

    private void workerextract_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        btnExtract.IsEnabled = true;
        System.Windows.MessageBox.Show("CSV Data extraction finished!");
    }

Я обнаружил, что

private void workerextract_ProgressChanged (отправитель объекта, System.ComponentModel.ProgressChangedEventArgs e)

вызывается один раз в конце, когда 100%. Также

private void workerextract_RunWorkerCompleted (отправитель объекта, RunWorkerCompletedEventArgs e)

никогда не звонил, так как я не вижу окно сообщения в конце.

Итак, я думаю, что я делаю что-то не так, не могли бы вы указать мне правильный путь?

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

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

 private void workerextract_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            try
            {
                this.Dispatcher.Invoke(() =>
                {
                    di = new DirectoryInfo(txtQueryfolder.Text);
                });
                    files = di.GetFiles("*.sql").Count();
                    currentfile = 0;

                foreach (FileInfo fi in di.GetFiles("*.sql"))
                {
                    // Open the text file using a stream reader.
                    using (StreamReader sr = new StreamReader(fi.FullName))
                    {
                        // Read the stream to a string, and write the string to the console.
                        string line = sr.ReadToEnd();

                        this.Dispatcher.Invoke(() =>
                        {
                        //System.Windows.MessageBox.Show(line);
                        ExtractToCSV(line, System.IO.Path.GetFileNameWithoutExtension(fi.Name));
                        });

                        currentfile++;
                    }
                    int percentage = (currentfile + 1) * 100 / files;
                    workerextract.ReportProgress(percentage);
                }
        }
        catch(Exception ex)
        {
            System.Windows.MessageBox.Show(ex.Message);
        }
    }

Спасибо всем за указание направления.

0 голосов
/ 09 мая 2018

Используя this.Dispatcher.Invoke в событии BackgroundWorker DoWork, вы выполняете всю операцию в потоке пользовательского интерфейса; это то, что BackgroundWorker рождено, чтобы не делать.

Кроме того, вы получаете сообщение об ошибке при развертывании кода от диспетчера, поскольку вы обращаетесь к объекту пользовательского интерфейса, который txtQueryfolder.

Просто используйте:

private void workerextract_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    string queryFolder = e.Argument.ToString();
    try
    {
        DirectoryInfo di = new DirectoryInfo(queryFolder);
        files = di.GetFiles("*.sql").Count();
        currentfile = 0;

        foreach (FileInfo fi in di.GetFiles("*.sql"))
        {
            // Open the text file using a stream reader.
            using (StreamReader sr = new StreamReader(fi.FullName))
            {
                // Read the stream to a string, and write the string to the console.
                string line = sr.ReadToEnd();

                //System.Windows.MessageBox.Show(line);

                // ExtractToCSV shouldn't access to a UI object.
                ExtractToCSV(line, System.IO.Path.GetFileNameWithoutExtension(fi.Name));
                currentfile++;
            }
            int percentage = (currentfile + 1) * 100 / files;
            workerextract.ReportProgress(percentage);
        }
    }
    catch (Exception ex)
    {
        // Don't use MessageBox in a thread different from the UI one. Just set the result (e.Result) and get that in the RunWorkerCompleted event.
        // System.Windows.MessageBox.Show(ex.Message);
    }
}

Когда вы вызываете метод RunWorkerAsync, просто добавьте параметр, как показано ниже:

workerextrac.RunWorkerAsync(txtQueryfolder.Text);
...