Using BackgroundWorker with ProgressBar in WPF

后端 未结 2 863
一个人的身影
一个人的身影 2020-12-18 12:21

Hi i have an App where one of the jobs will be convert an Excel and pass all the records to the DB.

So this takes a little time because it\'s more than 7000 rows tha

相关标签:
2条回答
  • 2020-12-18 12:37

    Here's an example of a background worker with progress.

    However, double-check to make sure a BGW will work in your situation. If you're controlling Excel via COM interop, it may require an STA thread (and a BGW is an MTA thread, not STA).

    If that's the case, you'll need to use a Task with an STA scheduler, or your own manual Thread (I strongly suggest the Task-based approach).

    0 讨论(0)
  • 2020-12-18 12:42

    I like to use bindings for ProgressBars (and pretty much everything else where possible) because that way you do not need to worry about dispatching to the UI thread.

    Basically you create some class that implements INotifyPropertyChanged with a progress property that you can bind your ProgressBar to. 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));
            }
        }
    }
    

    This class uses an event in the constructor which will update the Task's progress if raised but you can handle the Progress change in any way you like, e.g. a method or by making the Progress property public so you can just change it arbitrarily.


    Usage example:

    <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();
    }
    
    0 讨论(0)
提交回复
热议问题