I'm building a single window WPF application In the window is a list items (which are persisted in a database of course) Periodically I need to start a background task that updates the database from an Atom feed. As each new item is added to the database, the list in the UI must also update to reflect this. I don't want this background task to slow down the UI but at the same time it needs to interact with the UI.
Having read loads of articles and seen lots of simple examples, I am still unsure of the best way to implement this.
What I think maybe I could do is:
On the Window_Loaded event, create a DispatchTimer. When the Tick event fires, call UpdateDb() method. UpdateDB() will get the items from the Atom feed and add to the database. As I iterate through each item I will call another method to rebind the list to the database so that it "refreshes". When all the tasks are finished reset the DispatchTimer ??? (not sure if this can / needs to be / done).
Remember, this is background task so a user could be using the UI at the same time.
How does this sound?
Thanks.
I'd use a System.Threading.Timer, which will call a specified method at a specified interval on a threadpool thread, so no need to create an additional thread, do your db work with that and marshal back to the ui thread as needed.
Your approach would work.
You'd start the timer when the app loads. For each tick of the timer, you start a thread to update the database. Once the database update has happened, you can call
.BeginInvoke()
on your UI objects to update the UI on the presentation thread (that will be the only time your UI should be affected).WPF Multithreading with BackgroundWorker by Pavan Podila:
This sounds suboptimal because you're doing database connectivity on the UI thread. When the
Tick
event fires on theDispatcherTimer
, handlers will execute on the UI thread. You need to minimize the amount of work you do on this thread to keep the UI responsive, and you definitely shouldn't be doing IO-bound work on this thread.I would probably have a data service whose responsibility is to update the database and raise events as changes are made. Your UI layer can attach to these events and marshal to the UI thread to apply changes. To marshal to the UI thread, you just need to call
Dispatcher.Invoke
.Regardless of your specific approach, the key is to do as much as you can (including any database access) on a separate thread. Marshal back to the UI thread as late as possible and do as little work as possible on the UI thread.
One other thing to note is that WPF automatically marshals changes to scalar values for you. You only need to marshal changes to collections (adding/removing/replacing items).