2009-08-27 29 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

相關問題