简体   繁体   English

BackgroundWorker的进度栏不起作用

[英]BackgroundWorker's progress bar is not working

The BackgroundWorker's progressbar is not updated while doing some tasks. 在执行某些任务时,不会更新BackgroundWorker的进度栏。 What I would like to reach is progressbar moving while iterating through each file in DirectoryInfo. 我想到达的是在DirectoryInfo中遍历每个文件时移动的进度条。 Suppose we have 20 files of ".sql" while first file completed it should be 5%, 10% and etc. Here is my code. 假设我们有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!");
    }

I found that 我找到

private void workerextract_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) 私有void workerextract_ProgressChanged(对象发送者,System.ComponentModel.ProgressChangedEventArgs e)

is called once at the end when 100%. 100%结束时被调用一次。 Also, 也,

private void workerextract_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 私有void workerextract_RunWorkerCompleted(对象发送者,RunWorkerCompletedEventArgs e)

never called as I do not see Message Box at the end. 从来没有打电话,因为我没有看到最后的消息框。

So, I think I am doing something wrong here, could you please direct me on right way? 所以,我认为我在这里做错了,您能以正确的方式指导我吗?

Using this.Dispatcher.Invoke in the BackgroundWorker 's DoWork event you are executing the whole operation in the UI thread; 使用BackgroundWorkerDoWork事件中的this.Dispatcher.Invoke ,您将在UI线程中执行整个操作。 which is what BackgroundWorker born to avoid to do. 这是BackgroundWorker天生避免做的事情。

Also, you get an error unwrapping your code from the dispatcher because you are accessing an UI object, which is txtQueryfolder . 另外,由于要访问UI对象txtQueryfolder ,因此从调度程序txtQueryfolder

Just use: 只需使用:

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);
    }
}

When you call the RunWorkerAsync method just add the parameter like below: 调用RunWorkerAsync方法时,只需添加如下参数:

workerextrac.RunWorkerAsync(txtQueryfolder.Text);

The problem was in wrapping whole DoWork inside Dispatcher.Invoke. 问题在于将整个DoWork包装在Dispatcher.Invoke中。 I need to wrap only those code where it is interacting with UI. 我只需要包装那些与UI交互的代码。 So I changed the code appropriately and it works. 所以我适当地更改了代码,它可以工作。

 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);
        }
    }

Thanks to all for showing the direction. 感谢大家展示方向。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM