在WPF中使用BackgroundWorker和ProgressBar

时间:2011-04-25 01:38:58

标签: c# wpf multithreading wpf-controls backgroundworker

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

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

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

因此,如果我正在创建我创建的这个Job in Class,那么在我的情况下如何使用backgroundWorker向progessBar报告进度?

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

我认为,这只是一个提示,可能是好的或不是,我首先得到excel中的行数,将该数字作为ProgressBar中的一些Maxvalue,然后为每一行或在一个区间中我报告进展情况。

这可能吗?我该怎么办?

2 个答案:

答案 0 :(得分:4)

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

基本上,您创建了一个实现INotifyPropertyChanged的类,其中包含可以将ProgressBar绑定到的progress属性。 e.g。

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更改,例如方法或通过制作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();
}

答案 1 :(得分:0)

以下是background worker with progress的示例。

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

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