【问题标题】:Using BackgroundWorker with ProgressBar in WPF在 WPF 中使用带有 ProgressBar 的 BackgroundWorker
【发布时间】:2011-04-25 01:38:57
【问题描述】:

您好,我有一个应用程序,其中一项工作将转换 Excel 并将所有记录传递到数据库。

所以这需要一点时间,因为我将获取超过 7000 行并将其插入到数据库中。

所以因为这项工作需要一点时间,超过 3 分钟,我想使用 ProgressBar 来报告这项工作的进度。

因此,如果我在我创建的 Class 中执行此作业,在我的情况下,我如何使用 backgroundWorker 向 progessBar 报告进度?

我的目标是准确了解进度的百分比,以及我如何使用所有这些东西来报告进度。我从未使用过 backgroundWorkers。

我认为,这只是一个提示,无论好坏,我首先获取 excel 中的行数,将该数字作为 ProgressBar 中的某个 Maxvalue,然后在每个 Row 或间隔中我报告进度。

这可能吗?我该怎么做?

【问题讨论】:

    标签: c# wpf multithreading wpf-controls backgroundworker


    【解决方案1】:

    我喜欢为 ProgressBars (以及几乎所有其他可能的东西)使用绑定,因为这样您就不必担心dispatching to the UI thread

    基本上,您创建了一些实现INotifyPropertyChanged 的类,该类具有您可以将ProgressBar 绑定到的progress 属性。例如

    public class Task : INotifyPropertyChanged
    {
        private int _progress = 0;
        public int Progress
        {
            get { return _progress; }
            private set
            {
                if (_progress != value)
                {
                    _progress = value;
                    OnPropertyChanged("Progress");
                }
            }
        }
    
        public Task(ref ProgressChangedEventHandler progressChangedEvent)
        {
            progressChangedEvent += (s, e) => Progress = e.ProgressPercentage;
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
    

    此类在构造函数中使用一个事件,如果引发该事件,它将更新任务的进度,但您可以以任何您喜欢的方式处理进度更改,例如一个方法或通过将 Progress 属性设置为public,这样您就可以任意更改它。


    使用示例:

    <ProgressBar Minimum="0" Maximum="100" Height="20"
                 Value="{Binding UpdateTask.Progress, Mode=OneWay}"/>
    
    // The event that should be raised when a progress occurs.
    private event ProgressChangedEventHandler UpdateProgressChanged;
    
    // The task the ProgressBar binds to.
    private readonly Task _updateTask;
    public Task UpdateTask
    {
        get { return _updateTask; }
    }
    
    public MainWindow()
    {
        // Instatiate task, hooking it up to the update event.
        _updateTask = new Task(ref UpdateProgressChanged);
    }
    
    private void OnUpdateProgressChanged(int progressPercentage)
    {
        if (UpdateProgressChanged != null)
        {
            UpdateProgressChanged(this, new ProgressChangedEventArgs(progressPercentage, null));
        }
    }
    
    // Simple progress simulation
    private void Button1_Click(object sender, RoutedEventArgs e)
    {
        int progress = 0;
        DispatcherTimer timer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(0.5) };
        timer.Tick += (sSub,eSub) =>
        {
            progress++;
            // Raise progress changed event which in turn will change
            // the progress of the task which in turn will cause
            // the binding to update which in turn causes the value
            // of the ProgressBar to change.
            OnUpdateProgressChanged(progress);
            if (progress == 100)
            {
                timer.Stop();
            }
        };
        timer.Start();
    }
    

    【讨论】:

    • 好的,如果我想将我在这里所做的事情的进度绑定到进度条,我使用Progress 属性,对吗?你能举一个将进度条绑定到这个属性的例子吗?
    • 添加了一个例子,也修复了任务类的一个错误,costructor需要通过引用获取事件(ref关键字)。
    • 也许是你的binding is broken,我对此进行了测试,它确实有效。
    • 好的,我创建了一个新的 wPF App 项目,并在此处选取了您的示例,并对其进行了测试,并在 OnUpdatedProgressChanged 方法的末尾发现值是否正在 progBar 中更新,每次progress 属性增加时,我都使用了一个messageBox 来显示progressbar 的值,并且该值不会改变。它始终为 0,但属性正在递增...
    • 正如我之前所说的,does the binding work,输出窗口中是否有任何错误?我的代码不完整,我使用 DataContext 进行绑定。如果不熟悉绑定read the overview
    【解决方案2】:

    这是background worker with progress 的示例。

    但是,请仔细检查以确保 BGW 可以在您的情况下工作。如果您通过 COM 互操作控制 Excel,则可能需要 STA 线程(而 BGW 是 MTA 线程,而不是 STA)。

    如果是这种情况,您需要使用TaskSTA scheduler,或者您自己的手册Thread(我强烈建议使用基于Task 的方法)。

    【讨论】:

    • 是的,我正在使用 Com Interop。所以你说的Task方法是backgroudn worker中提到的,有进度链接,对吧?
    • 是的,除非你必须使用我链接到的StaTaskScheduler
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    相关资源
    最近更新 更多