2013-03-21 70 views
3

我有一個ConcurrentStack,其中每個項目都是一些網絡資源的URL。此外,我有N個線程(實際上是Tasks),每個線程從堆棧進程中彈出一個項目,並根據某些條件將結果(結果爲集合)添加到此堆棧或其他輸出隊列。這應該完成,直到堆棧變空。幾個線程中的進程堆棧項目

什麼是更優雅的方式來識別此過程的結束並停止此任務?在換句話說,如何認識到堆棧是空的,沒有執行的任務,將

+1

您正在描述消費者如何工作,但您的問題是關於生產者。 – adrianm 2013-03-21 09:17:58

回答

2

終止條件似乎是從堆棧讀取的所有任務都是全部等待一個項目堆疊堆棧。當然,這隻有在你爲任務提供一種被動地等待該事件的方式時纔會發生。正如其他答案所建議的那樣,您可以在ConcurrentStack類的頂部使用BlockingCollection來實現同步。

關於終止,最簡單的方法是讓一個任務(終止任務)等待該條件,其他所有任務操作一個整數,表示等待的任務數,在對集合進行阻塞之前對其進行遞增,並將其遞減當獲得一個項目。當該數字達到堆棧可能的讀取器總數時,當前嘗試獲取項目的任務會在集合上阻塞之前觸發條件變量,這會喚醒終止線程。

1

由於您使用的是ConcurrentStack,它實現IProducerConsumerCollection添加更多的項目到堆棧,你可以用BlockingCollection把它包裝(通過使用this constructor創建一個)。這提供了一個可以指示數據結束的方法。

底層的IProducerConsumerCollection將用於存儲這些項目,因此它在LIFO方面的表現仍然像堆棧一樣。

您將需要切換到使用GetConsumingEnumerable()重載之一來使用數據。我覺得這是處理優雅任務終止的最優雅和最強大的方式。

也許這可能適合你?

+0

感謝您的回答,我不知道是否可以將BlockingCollection作爲堆棧擴展,但是我的所有線程都不知道是否應該調用CompleteAdding,因爲沒有人知道其他人是否要添加更多的項目 – 2013-03-21 09:15:01

+0

Well * something * must know - that something must call'CompleteAdding()'。 – 2013-03-21 09:18:47