-2

How can I report back on the progress of work carried out by a BackgroundWorker in an object in a class library?

I'm so far not sure how to use ReportProgress to feed back the information (can't refer to the calling class, due to circular dependency).

This is an example of the main project which initiates the work:

namespace MainProject {
    class MainWindowVM : INotifyPropertyChanged {
        private BackgroundWorker _counterWorker;

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private int _progress;
        public int Progress {
            get { return _progress; }
            set { _progress = value; NotifyPropertyChanged(); }
        }

        public MainWindowVM() {
            var heavyWorker = new ClassLibrary.HeavyWorkerClass();
            _counterWorker = new BackgroundWorker();
            _counterWorker.DoWork += new DoWorkEventHandler(_counterWorker_DoWork);
            _counterWorker.RunWorkerAsync(heavyWorker);

        }

        private void _counterWorker_DoWork(object sender, DoWorkEventArgs e) {
            var heavyWorker = (ClassLibrary.HeavyWorkerClass)e.Argument;
            heavyWorker.StartWork();
            Progress = 100;
            System.Windows.MessageBox.Show("Work completed!");
        }
    }
}

And here's an example of the uploading method in a class library:

namespace ClassLibrary {
    public class HeavyWorkerClass {
        public void StartWork() {
            for (int i = 0; i <= 100; i++) {
                Thread.Sleep(50);
            }
        }
    }
}
Oystein
  • 1,232
  • 11
  • 26
  • 1
    take a look to `ReportProgress` method? [there](https://www.codeproject.com/Articles/99143/BackgroundWorker-Class-Sample-for-Beginners) is one of many tutorials on this – lena Apr 06 '17 at 07:52
  • 2
    Without a good [mcve] that clearly illustrates whatever problem you're having, it's not possible to know what answer you need (any person posting an answer is just guessing, and has no real business doing so). If you write your WPF program "normally", then you have view models, implementing `INotifyPropertyChanged`, bound to UI objects, and you can just set the view model property values as needed. WPF will handle all the cross-thread stuff for you. If you are not writing WPF in the normal way, then it gets more complicated, but without a MCVE, the precise details vary. – Peter Duniho Apr 06 '17 at 07:54
  • Possible duplicate of [Update GUI using BackgroundWorker](http://stackoverflow.com/questions/5192169/update-gui-using-backgroundworker) – Massimiliano Kraus Apr 06 '17 at 08:24
  • @PeterDuniho Thanks for the feedback about MCVE. Please see the edited question. – Oystein Apr 06 '17 at 09:11

2 Answers2

1

The HeavyWorkerClass must report its progress somehow. Othwerwise you cannot be supposed to know anything about the progress.

It could for example raise an event at regular intervals. The view model can then subscribe to this event and update its Progress property accordingly. The view binds to the Progress property of the view model.

Note that it is pretty uncommon for a service or class library method to report its progress though. This is because in most cases there is simply no API that can reveal the current progress of an operation in flight. In situations like this you might as well choose to display an intermediate ProgressBar or similar in the UI until the operation has finished:

<ProgressBar IsIndeterminate="True" />
mm8
  • 163,881
  • 10
  • 57
  • 88
  • Ah, of course! I can just move the Progress property to inside HeavyWorkerClass, and have it implement INotifyPropertyChanged as well. If I also add a public get property for the HeavyWorkerClass object inside MainWindowVM, the View can bind to the Progress property inside HeavyWorkerClass directly. Thanks a lot for the tip! – Oystein Apr 06 '17 at 10:56
  • On a side note, I don't want to use IsIndeterminate, as (1) the process varies a lot in how long it runs and (2) it isn't indeterminate. – Oystein Apr 06 '17 at 10:58
0

Following mm8's solution, here's the updated code.

Main project initiating the work:

namespace MainProject {
    class MainWindowVM : INotifyPropertyChanged {
        private BackgroundWorker _counterWorker;

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private ClassLibrary.HeavyWorkerClass _heavyWorker;
        public ClassLibrary.HeavyWorkerClass HeavyWorker {
            get { return _heavyWorker; }
        }

        public MainWindowVM() {
            _heavyWorker = new ClassLibrary.HeavyWorkerClass();
            _counterWorker = new BackgroundWorker();
            _counterWorker.DoWork += new DoWorkEventHandler(_counterWorker_DoWork);
            _counterWorker.RunWorkerAsync(_heavyWorker);
        }

        private void _counterWorker_DoWork(object sender, DoWorkEventArgs e) {
            var heavyWorker = (ClassLibrary.HeavyWorkerClass)e.Argument;
            heavyWorker.StartWork();
            System.Windows.MessageBox.Show("Work completed!");
        }
    }
}

HeavyWorkerClass that does the time-consuming work:

namespace ClassLibrary {
    public class HeavyWorkerClass : INotifyPropertyChanged {

        private int _progress;
        public int Progress {
            get { return _progress; }
            set {
                _progress = value;
                NotifyPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public void StartWork() {
            for (int i = 0; i <= 100; i++) {
                Progress = i;
                Thread.Sleep(50);
            }
        }
    }
}
Community
  • 1
  • 1
Oystein
  • 1,232
  • 11
  • 26