2012-02-08 50 views
0

我有一個Web服務,我需要抓住一堆記錄並對每個記錄進行一些處理。這種處理可能每行都很冗長,我以線程方式運行這部分代碼,將行數據作爲參數傳遞給函數。我可以有1000或更多的行來處理,並且我將數據處理線程的數量限制爲10.如何產生線程並在Web服務中管理?

爲了監視我的線程,我有一個Thread對象數組。

Dim RowThread(9) As Thread 

在我的主線程(Web服務的WebMethod)之前,我產生一個新的線程我遍歷這個數組,尋找我的下一個「可用」的線程。

Dim avail_thread As Integer = -1 
While avail_thread < 0 
    For t As Integer = 0 To THREADCOUNT - 1 
     If IsNothing(RowThread(t)) OrElse Not RowThread(t).IsAlive Then 
      avail_thread = t 
      Exit For 
     End If 
    Next 
End While 

...

RowThread(avail_thread) = New Thread(New ParameterizedThreadStart(AddressOf ProcessRow)) 

...

RowThread(avail_thread).Start(row) 

正如你所看到的,此等待線程完成,將產生的下一個可用線程的下一行。如果所有10個線程都在使用中,它將繼續循環並等待一個線程,因爲可用。

這種方法很好,在大多數服務器上運行良好。除了最近在某些服務器上,我注意到這會導致問題,因爲它在此循環中阻止了CPU。這會影響整體性能,因爲我的主線程正在浪費大量的CPU週期。爲了緩解這個問題,我嘗試了線程Sleep()甚至DoEvents(),但是這些方法只會進一步降低性能。

是否有其他人遇到過這種情況?我真的不認爲我可以使用委託等。因爲這是在一個Web服務中,我不希望我的主要調用被終止,因爲我不想在所有行都被處理之前發送結果。與ThreadPool相同的問題,更不用說ThreadPool的確給你儘可能多的控制。

如何負責任地產生並管理Web服務中的線程?有沒有辦法執行非阻塞手動線程監控?

+0

您使用的是什麼版本的.NET?如果使用.NET 4.0,則應該嘗試使用Parallel.ForEach。 – 2012-02-08 19:29:33

回答

2

爲什麼不把所有的工作都發布到線程池?它將以完全正確和有效的方式爲您做到這一切。它會創建適當數量的線程並在其中分配工作項目。當你使用TPL的Task類時,你甚至可以監視任務完成。

+0

我想過使用線程池,但是我可以從字面上加載1000+個請求嗎?我正在閱讀的數據來自數據庫,並將該行的數據傳遞給每個線程。排隊時,1000行以上的數據位於哪裏?可能是內存,如果我正在用BLOB等處理數據,那麼我不想用完。 – nullvalue 2012-02-08 18:45:20

0

我想我在WaitHandle中找到了答案。在我之前的研究中,我認爲只能將這些與ThreadPool一起使用,但事實證明,您也可以將它們與手動啓動的線程一起使用。

我現在使用:

RowEvents(avail_thread) = New ManualResetEvent(False) 

後來在通過這個上線開始我的參數對象的一部分。當該函數完成時,我爲該線程的ManualResetEvent對象執行Set()。

現在我找到下一個可用線程的代碼如下所示:

Dim avail_thread As Integer = -1 
While avail_thread < 0 
    For t As Integer = 0 To THREADCOUNT - 1 
     If IsNothing(RowThread(t)) OrElse Not RowThread(t).IsAlive Then 
      avail_thread = t 
      Exit For 
     End If 
    Next 
    'All threads busy, call blocking wait 
    If avail_thread < 0 Then avail_thread = WaitHandle.WaitAny(RowEvents) 
End While 

這將通過現在所有10個線程在第一輪..循環,如果他們都在運行,然後我調用了WaitAny方法,重點當任何線程完成並將我的avail_thread變量設置爲已完成的索引線程時返回。