我有這個生產者/消費者代碼:Monitor.Pulse丟失信號?
MAIN:
static void Main()
{
using(PCQueue q = new PCQueue(2))
{
for(int i = 0; i < 10; i++)
{
int itemNumber = i; // To avoid the captured variable trap
q.EnqueueItem(() = > {
Thread.Sleep(1000); // Simulate time-consuming work
Console.Write(" Task" + itemNumber);
});
}
Console.WriteLine("Enqueued 10 items");
Console.WriteLine("Waiting for items to complete...");
}
}
類:
public class PCQueue: IDisposable
{
readonly object _locker = new object();
Thread[] _workers;
Queue <Action> _itemQ = new Queue <Action>();
public PCQueue(int workerCount)
{
_workers = new Thread[workerCount];
// Create and start a separate thread for each worker
for(int i = 0; i < workerCount; i++)
(_workers[i] = new Thread(Consume)).Start();
}
public void Dispose()
{
// Enqueue one null item per worker to make each exit.
foreach(Thread worker in _workers) EnqueueItem(null);
}
public void EnqueueItem(Action item)
{
lock(_locker)
{
_itemQ.Enqueue(item); // We must pulse because we're
Monitor.Pulse(_locker); // changing a blocking condition.
}
}
void Consume()
{
while(true) // Keep consuming until
{ // told otherwise.
Action item;
lock(_locker)
{
while(_itemQ.Count == 0) Monitor.Wait(_locker);
item = _itemQ.Dequeue();
}
if(item == null) return; // This signals our exit.
item(); // Execute item.
}
}
}
問:
比方說執行的item();
需要很長的時間。
1) we enqueue a new work and pulse. (1 consumer is busy now)
2) we enqueue a new work and pulse. (second consumer is busy now)
3) we enqueue a new work and pulse.
現在呢?兩個線程都很忙!
我know,脈衝會丟失(或不?)
是唯一的解決辦法是將其更改爲AutoResetEvent
?
System.Collections.Concurrent.BlockingCollection有什麼問題?如果你想DIY,你可以使用System.Threading.Semaphore和一個鎖。對於生產者 - 消費者隊列來說,事件並不是一個合適的解決方案 - 我不知道爲什麼如此之多的開發者被欺騙使用它們來達到這個目的。 – 2012-08-02 13:48:02
@MartinJames沒有錯。我只想知道如何增強代碼,並檢查我的假設是否正確。 – 2012-08-02 13:49:07
@MartinJames我猜你必須問Joe Albahari關於你的問題.http://books.google.co.il/books?id = VENrFSQFco8C&pg = PA846&lpg = PA846&dq =%22 + To + avoid + the + captured + variable +阱%22&源= BL&OTS = 3uV-ribX9Q&SIG = gjsMPGyZD6H-DgcwjR_vuv5V8aI&HL = EN&SA = X&EI = noUaUJKpLcem0QXHsYC4Cw&redir_esc = Y#v = onepage&q =%22%20To%20avoid%第二十條%20captured%20variable%20trap%22&F =假 – 2012-08-02 13:51:09