2009-08-27 31 views
2

我正在构建一个窗口WPF应用程序 窗口中是一个列表项目(当然是保存在数据库中) 定期我需要启动一个后台任务从Atom提要更新数据库。随着每个新项目被添加到数据库中,UI中的列表也必须更新以反映这一点。我不希望这个后台任务放慢UI,但同时它需要与UI进行交互。针对WPF应用程序的多线程策略所需的建议

阅读过大量的文章,并看到很多简单的例子,我仍然不确定实现这一点的最佳方式。

我觉得也许我可以做的是:

在Window_Loaded事件,创造一个DispatchTimer。 当Tick事件触发时,调用UpdateDb()方法。 UpdateDB()将从Atom提要中获取项目并添加到数据库。当我迭代每个项目时,我会调用另一种方法将列表重新绑定到数据库,以便“刷新”。 当所有的任务完成后重置DispatchTimer ??? (不知道这是否可以/需要/完成)。

请记住,这是后台任务,因此用户可以同时使用UI。

听起来如何?

谢谢。

回答

2

这听起来并不理想,因为您正在UI线程上进行数据库连接。当Tick事件在DispatcherTimer上触发时,处理程序将在UI线程上执行。你需要尽量减少你在这个线程上做的工作量,以保持UI的响应,你绝对不应该在这个线程上进行IO绑定工作。

我可能会有一个数据服务,其职责是更新数据库并在发生更改时引发事件。您的UI层可以附加到这些事件并编组到UI线程以应用更改。要编组到UI线程,您只需拨打Dispatcher.Invoke即可。

无论您的具体做法如何,关键是要在单独的线程上尽可能地做到(包括任何数据库访问)。尽可能晚的回到UI线程,并在UI线程上尽可能少地工作。

还有一点需要注意的是,WPF会自动将更改更改为标量值。您只需要对集合进行编组(添加/删除/替换项目)。

+0

我喜欢这种声音。我不需要数据服务,因为我已经有一个管理类来处理数据库工作。 UI中没有数据库工作正在发生。我只是想简单地解释我的问题的背景信息。 – empo 2009-08-28 08:47:23

0

你的方法可行。

你会在应用程序加载时启动计时器。对于计时器的每个滴答声,您都会启动一个线程来更新数据库。一旦数据库更新发生,您可以在您的UI对象上调用.BeginInvoke()来更新演示线程上的UI(这将是您的UI唯一受影响的时间)。

+0

如果所有的DispatcherTimer都启动了另一个线程,那么使用DispatcherTimer有什么意义? – 2009-08-27 15:53:20

+0

因为它启动的线程可以在不阻塞UI线程的情况下完成更新数据库的繁重工作......并且DispatchTimer将按计划启动这些线程而不是一次性启动。 – 2009-08-27 15:55:10

+0

是的,但这些线程不需要在UI线程上启动。你可以使用一个普通的定时器,并避免完全中断用户界面;) – 2009-08-27 16:01:06

0

我会使用一个System.Threading.Timer,它将在一个线程池线程上以指定的时间间隔调用指定的方法,因此不需要创建一个额外的线程,让你的数据库工作,然后编组回到根据需要使用ui线程。

0

WPF Multithreading with BackgroundWorker由帕Podila:

好消息是,你真的不必写这样的成分,因为一个是已经可用:在.Net框架2.0中引入的BackgroundWorker类。熟悉WinForms 2.0的程序员可能已经使用过这个组件。但BackgroundWorker与WPF一样好,因为它对线程模型完全不可知。

+0

我不认为这适用于我,因为我需要在任务运行时访问UI对象。我认为会因为尝试从另一个线程访问UI而抛出异常。 – empo 2009-08-28 08:41:28

+0

看看“C#中的后台工作者 - 线程简单”(http://www.nerdparadise.com/tech/coding/csharp/backgroundworker/),看看ProgressChangedEventHandler()如何不能为您工作。 – rasx 2009-08-28 16:16:20

相关问题