Advice needed for multi-threading strategy for WPF

2020-07-26 14:54发布

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.

4条回答
时光不老,我们不散
2楼-- · 2020-07-26 15:21

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.

查看更多
虎瘦雄心在
3楼-- · 2020-07-26 15:32

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).

查看更多
成全新的幸福
4楼-- · 2020-07-26 15:36

WPF Multithreading with BackgroundWorker by Pavan Podila:

The good news is that you really don’t have to write such a component since one is available already: the BackgroundWorker class introduced in .Net Framework 2.0. Programmers who are familiar with WinForms 2.0 may have already used this component. But BackgroundWorker works equally well with WPF because it is completely agnostic to the threading model.

查看更多
Fickle 薄情
5楼-- · 2020-07-26 15:42

This sounds suboptimal because you're doing database connectivity on the UI thread. When the Tick event fires on the DispatcherTimer, 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).

查看更多
登录 后发表回答