這很容易通過Semaphore完成。
這個想法是創建一個最大計數爲N的信號量,其中N是允許的線程數。循環在信號量上等待,並在獲取信號量時排隊任務。
Semaphore ThreadsAvailable = new Semaphore(10, 10);
while (Queue.Count > 0)
{
ThreadsAvailable.WaitOne();
// Must dequeue item here, otherwise you could run off the end of the queue
ThreadPool.QueueUserWorkItem(DoStuff, Queue.Dequeue());
}
// Wait for remaining threads to finish
int threadCount = 10;
while (threadCount != 0)
{
ThreadsAvailable.WaitOne();
--threadCount;
}
void DoStuff(object item)
{
ItemType theItem = (ItemType)item;
// process the item
StartProcessing(item);
// And then release the semaphore so another thread can run
ThreadsAvailable.Release();
}
該項目在主循環中出隊,因爲這樣可以避免競爭條件,否則這些條件很難處理。如果讓線程出列的項目,那麼線程必須做到這一點:
lock (queue)
{
if (queue.Count > 0)
item = queue.Dequeue();
else
// There wasn't an item to dequeue
return;
}
否則,事件將按照下列順序可能是當只有一個留在隊列項出現。
main loop checks Queue.Count, which returns 1
main loop calls QueueUserWorkItem
main loop checks Queue.Count again, which returns 1 because the thread hasn't started yet
new thread starts and dequeues an item
main loop tries to dequeue an item and throws an exception because queue.Count == 0
如果你願意這樣處理事情,那麼你沒事。關鍵是在線程退出之前確保線程在信號量上調用Release
。您可以使用顯式託管的線程或使用我發佈的ThreadPool
方法來完成此操作。我只是使用ThreadPool
,因爲我覺得比顯式管理線程更容易。
TPL在.NET 3.5中可用。 [.NET 3.5的任務並行庫](http://nuget.org/packages/TaskParallelLibrary/) – Romoku 2013-05-06 16:47:21
無論如何,創建1個線程來取消1個項目並不是非常有效。沒有必要Join()在這裏,想一想更好的控制流程。 – 2013-05-06 16:53:24