我有一個線程控制檯應用程序工作正常,但它的架構需要改進,我想要一些反饋。C#鎖定和一般線程設計問題
目前,程序加載一個數據列表,並將數據分割成分區(每個線程一個塊)。然後,程序使用ThreadPool初始化一個新線程,並將其傳遞給要運行的一部分分區數據。
一切都很好地工作...除了:
一些線程失敗......由於網絡問題,或無法恢復的異常。這是預期的行爲,而不是一個錯誤。
我現在需要一種方法(如果線程失敗)恢復該線程的數據段並將其提供給另一個工作線程以使其不成爲孤立。我確信有辦法做到這一點,即在線程之間共享數據等,但我認爲有一個更好的方法。
而不是事先分割數據並將其傳遞給每個線程,我可以在所有線程之間共享此數據的一個靜態集合。這更優雅,但引入了舊方法不必擔心的新同步問題。答案:
A.)你對這種方法和舊方法有什麼想法?
B.)如果這種方法很好,我該如何去鎖定對共享靜態集合的訪問。
當線程進入時,我可以鎖定集合並彈出一段僅用於該線程的數據。現在,該靜態集合將被該線程彈出的數量減少。在線程失敗後,我可以通過再次鎖定數據段將數據段重新分配給共享集合,並將數據重新推送到集合中供其他線程嘗試處理。
例如:(未經測試的僞代碼)
void Process(object threadInfo)
{
lock(StaticCollection)
{
var segment = StaticCollection.Take(100);
StaticCollection.Remove(StaticCollection.Where(item => segment.Contains(item)))
}
foreach(var seg in segment)
{
// do something
}
// reallocate the thread's data on failure
if(unrecoverableErrorOccurred)
{
lock(StaticCollection)
{
StaticCollection.Add(segment);
}
}
}
我在正確的軌道與此有關?在我看來,一個線程可以在另一個線程重新分配項目的同時移除項目...或者對STATIC集合執行鎖定意味着根本沒有其他線程可以訪問該集合。因此,線程A.)在方法的第一部分獲得了一個鎖,它會阻止所有其他線程執行方法的最後部分,直到完成ThreadA爲止。
您的解決方案實際上非常好(除了撥打和撥打電話,您可能需要考慮使用實際的堆棧)。我喜歡你提供的解決方案,因爲它也可以讓你只將已經失敗的對象推回堆棧或隊列,並且不需要其他收集來跟蹤每個項目的處理狀態。 現在有人可能會尖叫,爲什麼這是可怕的... – LorenVS 2009-08-19 19:47:09
操作是否需要成功或失敗作爲一個單一的交易? (並且這個過程是否改變了它所在的部分的數據?) – 2009-08-19 20:06:23
這兩個數字都不是。 – Scott 2009-08-19 21:05:01