0

I'm using a BackgroundWorker and ive implemented ProgressChanged method which gives me e.UserState to pass to my UI, which works OK.

As an experiment I changed my DoWork Method to work on the same model that is bound to the UI ListView (which is an Observable Collection)

The UI updates when I do this, & im wondering why it manages to do it flawlessly after many tests?

Im going back to using the e.UserState object but im wondering if it is normal behaviour & whats the potential problems?

tinmac
  • 2,357
  • 3
  • 25
  • 41
  • First of all: what are you using as a GUI framework? I remember, for example, WinForms being exceptionally forgiving when called by a non-ui thread, and other frameworks having checks for code to use Invoke* instead of direct calls – Lorenzo Dematté Feb 27 '13 at 12:49
  • I'm assuming the ObservableCollection is bound directly to your View? – Bob. Feb 27 '13 at 12:50
  • Hey sorry I forget WPF tag, will add it now – tinmac Feb 27 '13 at 12:50
  • @dema80 Funny, I always have to use Invoke using WinForms. I though WPF was forgiving in that area. – Maarten Feb 27 '13 at 12:51
  • @Bob yes its bound direct – tinmac Feb 27 '13 at 12:53
  • 1
    WPF automatically marshals property changes to the UI thread. See http://stackoverflow.com/a/590609/863564 – Lorenzo Dematté Feb 27 '13 at 12:53
  • @Maarten WPF is "forgiving" if you use it correctly (i.e. if you let it do the marshaling itself); some part of Winforms just had no control on the current thread, IIRC (as a rule, it should not work...) – Lorenzo Dematté Feb 27 '13 at 12:55
  • 1
    See also this question: http://stackoverflow.com/questions/1321423/does-wpf-databinding-marshall-changes-to-the-ui-thread. As long as you just change properties in your model, WPF will automatically reflect changes in the UI using the correct dispatcher – Lorenzo Dematté Feb 27 '13 at 12:57

1 Answers1

2

You can certainly change your model's properties from a background thread without any trouble; the binding engine will determine what changes need to be made to UI elements and invoke those on the dispatcher thread¹. This is normal and will not result in problems.

What you cannot (and never could) do is directly change properties of UI elements from the same background thread.


¹This has always been possible, and in fact it couldn't be any other way. Consider that some code (e.g. a model) needs to change a property on another model. This code surely cannot know that the property has been bound to any control, much less which control that is. Therefore it would not only be inconvenient but also horribly difficult to marshal the property change off to the appropriate UI thread each time.

Jon
  • 428,835
  • 81
  • 738
  • 806
  • He's using an `ObservableCollection`, does the UI change even if he's editing items in the collection? I don't think `INotifyCollectionChanged.CollectionChanged` triggers if the collection isn't adding/removing items. – Bob. Feb 27 '13 at 13:02
  • Wow data binding really does have its virtue's. I get it now, model update form thread OK, UI update from thread - use ProgressChanged. Thankyou – tinmac Feb 27 '13 at 13:04
  • @TinoMclaren: There are a few gotchas here though -- what changes are you making exactly? Sample code? – Jon Feb 27 '13 at 13:05
  • @Jon I cant post the code right now but its properties like ProgressBar.Value which is in a LstView. Just reading up on marshaling, what gotchas am I to look out for? – tinmac Feb 27 '13 at 13:11
  • @TinoMclaren: Stuff like that (directly changing values) will always work, the binding engine does what it has to. However, you cannot do the same with things like `observableCollection.Add(stuff)` (not a property access, which is a strong hint that things are different). – Jon Feb 27 '13 at 13:20