C# 后台工作人员';的进度条不工作

C# 后台工作人员';的进度条不工作,c#,backgroundworker,C#,Backgroundworker,在执行某些任务时,BackgroundWorker的progressbar不会更新。我想了解的是,在遍历DirectoryInfo中的每个文件时,progressbar会移动。假设我们有20个“.sql”文件,而第一个完成的文件应该是5%、10%等等。 这是我的密码 private void CSV_Click(object sender, RoutedEventArgs e) { try {

在执行某些任务时,BackgroundWorker的progressbar不会更新。我想了解的是,在遍历DirectoryInfo中的每个文件时,progressbar会移动。假设我们有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!");
    }
我发现

私有void workerextract_ProgressChanged(对象发送方, System.ComponentModel.ProgressChangedEventArgs(e)

100%时,在结束时调用一次。 而且

私有无效工作提取\运行工作完成(对象发送方, RunWorkerCompletedEventArgs(e)

从未调用,因为我在末尾没有看到消息框


因此,我认为我在这里做错了什么,您能告诉我正确的方法吗?

使用
this.Dispatcher.Invoke
BackgroundWorker
DoWork
事件中执行UI线程中的整个操作;这就是
BackgroundWorker
天生要避免做的事情

此外,由于正在访问一个UI对象,即
txtQueryfolder
,因此从dispatcher中展开代码时会出现错误

只需使用:

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

问题是在Dispatcher.Invoke中包装整个DoWork。 我只需要包装那些与UI交互的代码。 因此,我适当地修改了代码,它可以正常工作

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

感谢大家为我们指明了方向。

为什么它会被多次调用?您只报告一次进度-在最后。你根本没有在循环中报告进度。我修改了我的代码,即使是在循环中,它也只调用一次。你需要创建一个后台工作程序,然后让
调度程序
将大部分代码移回UI线程。为什么要这样做?所以停止从后台工作代码访问UI对象。或者,如果您“必须”访问UI对象,只需使用
Dispatcher.Invoke
,而不是整个循环来包装这些行。为什么要生成一个后台工作程序来在UI线程上运行它
this.Dispatcher.Invoke
。这违背了整个目的这不是正确的方法,即使它有效。请看一下我的最新答案。还有,
extractocsv
的代码是什么?为什么它要访问UI对象?@OmarMuscatello在您的回答下面看到我的评论行ExtractToCSV(line,System.IO.Path.GetFileNameWithoutExtension(fi.Name));给出一个错误“调用线程无法访问此对象,因为另一个线程拥有它。”您应该发布
ExtractToCSV
函数的代码以获得帮助,或者尝试注释该函数的内容,看看它是否正常工作;只需调试它:)是的,如果我对ExtractToCSV进行注释,它就可以工作,我只是用Dispatcher打包了。调用该部分,似乎一切都很好,谢谢您的帮助。@FirdavsKurbonov,很高兴提供帮助。我很高兴你找到了答案,但这也不应该是正确的解决方案。迭代和执行
ExtractToCSV
函数是该方法花费时间的一部分。所有部分都应该在后台线程中执行。不过,这只是一个提示:)