2010-06-03 86 views
4

我有一個場景,我試圖通過預先獲取結果的一些子元素,如果可能的話,它們實際上是用戶需要之前變成一個更響應的用戶界面。我不清楚如何最好地處理線程,所以我希望有人能提供一些建議。ThreadPool適用於此線程場景嗎?

方案

有搜索表單(.NET富客戶端),使用戶能夠選擇一個帳戶對於一個給定的客戶。用戶搜索給定文本以查找一系列客戶,然後顯示在結果網格中。然後,當用戶選擇一個客戶時,該客戶的賬戶列表將被搜索並顯示在第二個網格中供用戶選擇,以便組成要打開的最終上下文(即賬戶)。

現有的系統

我使用定期後臺線程來解決客戶的請求/響應方式這一切運行,並在用戶選擇直接響應分別佔客戶。用戶界面被鎖定/禁用(但響應),直到找到帳戶。

目標

我想實現的是開始,用戶已經選擇在他們面前......其中N是顯示在網格項目的數量佔前N個客戶的獲取。

隨着用戶滾動網格,新顯示的項目將被添加到「隊列」中以便獲取。

問題

  1. 是線程池管理線程的適當機制?如果是這樣,你能強制一個排隊的工作項目優先跳躍嗎? - 例如如果用戶在開始/完成抓取之前選擇了該顧客。
  2. 如果不是,我還應該做些什麼?
  3. 無論哪種方式,您是否知道任何具有此功能的優秀博客帖子和/或開源項目?

回答

2

是的,線程池是一個不錯的選擇,可能在Backgroundworker或.NET4的TaskParallel庫後面。

但是你不能(不應該)'碰撞'一個ThreadPool線程,但我不認爲這將是有用的無論如何。

你應該做的是使用一個線程安全隊列(前N個項目)並使用2+線程來處理隊列。當一個項目被選中並且還沒有被處理時,你將它向上移動或立即啓動一個單獨的線程。

+1

只要您不介意可能被加載兩次並拋出舊副本的數據,cache-with-preloader方法絕對是最容易正確使用的方法。如果你正在加載有狀態或特別昂貴的東西,那麼你可能需要一個自動(延遲加載)緩存。 – Aaronaught 2010-06-03 16:26:41

0

如果.NET 4是一個選項,我可以推薦新的ConcurrentStack集合。

http://msdn.microsoft.com/en-us/library/dd267331(v=VS.100).aspx

您可以添加所有要預取的項目,如果一個項目是由用戶選擇,你可以把該選擇到堆棧上,使其要檢索的一個實例。這對於新的PLINQ和TPL很有效,並且使用了.NET 4中新的ThreadPool改進。

http://channel9.msdn.com/shows/Going+Deep/Erika-Parsons-and-Eric-Eilebrecht--CLR-4-Inside-the-new-Threadpool/

1

通過更新/解決方案的方式......我跟着Henk's溶液(排序),使得我一直在工作項目對象的隊列中,但我仍然使用線程池處理它們。選擇的項目通過將它們放在隊列的前面(而不是後面)來「碰撞」[注意:需要一個特殊的集合)。

以下(可能會詳細描述它(代替代碼)

  • 修改Customer保持的IList<Account>命名 KnownValues一個屬性,也用於鎖定命名對象KnownValuesSyncObject,因爲我想當KnownValues尚未知時,它們將爲null)。
  • 搜索形式保持一個實例變量Deque<CustomerAccountLoadingWorkItem>(從PowerCollections
  • 一個CustomerAccountLoadingWorkItem保持到它的意思過程,以及它的ManualResetEvent手柄,這與創建客戶參考。
  • 爲了僅開始加載可見項目(即,不從屏幕上滾動),我使用my other post的答案將Data Virtualization用作排隊加載每個「頁面」時CustomerAccountLoadingWorkItem的機制。在添加到工作項目隊列之後,立即將一個任務添加到ThreadPool隊列中。 ThreadPool.QueueUserWorkItem調用的上下文/狀態是我的_accountLoadingWorkItems隊列。
  • 由ThreadPool啓動的WaitCallback委託,將工作項隊列傳遞給它,然後(使用鎖)將頂層項出列(如果沒有,則立即返回);然後處理該項目。所使用的函數是一個靜態函數,作爲CustomerAccountLoadingWorkItem的一部分,以便它可以訪問它的私有隻讀狀態(即Customer和ManualResetEvent)。
  • 在處理結束時,靜態處理函數還設置Customer.KnownValues(使用KnownValuesSyncObject用於鎖定)。
  • 當用戶在Customers網格中選擇一個值時,如果Customer.KnownValues尚未填充(即它可能位於某處的隊列中),則它已經是單獨的線程(通過BackgroundWorker),然後它將新的CustomerAccountLoadingWorkItem添加到工作項目隊列(但在頂部!!! [這就是爲什麼需要Deque]),並且還向ThreadPool添加了一個新的處理任務。然後,由於它創建了工作項,它會調用ManaulResetEvent.WaitOne()強制等待線程池任務完成。

我希望是有道理的......

值得注意的是,因爲我的解決方案仍然使用線程池,當用戶選擇一個項目我還是要等待當前正在運行的線程池中的我的作品前完成項目被拿起,我認爲這是可以的,甚至可以看到,就好像用於查詢帳戶(web服務)的資源將被半鎖定一樣,它可能會快速地等同於快速(由於一些糟糕的架構和一個共享的Web服務代理)。總的來說,我當然做了本該容易理解的工作,這個工作稍微有些困難,而且我應該可以使用Framework 4,我一定會去看看TPL路線。