我遇到了一個我無法弄清楚的問題。這可能不容易解釋。在線程中啓動作業從其他線程的隊列中讀取
我有這個私有構造一個單例類:
private BarcodeMonitor()
{
processors[Machines.H1] = new BarcodeProcessor { Queue = new BlockingQueue<BarcodeData>("H1") };
processors[Machines.H2] = new BarcodeProcessor { Queue = new BlockingQueue<BarcodeData>("H2") };
processors[Machines.M] = new BarcodeProcessor { Queue = new BlockingQueue<BarcodeData>("M") };
processors[Machines.HP] = new BarcodeProcessor { Queue = new BlockingQueue<BarcodeData>("HP") };
foreach (KeyValuePair<Machines, BarcodeProcessor> pair in processors)
{
Thread t = new Thread(t1 => pair.Value.StartProccesingQueue());
t.Name = pair.Key.ToString() + "Processor";
t.Start();
threads.Add(t);
}
}
一個新的和獨特的BlockingQueue
是考慮到BarcodeProcessor
,並採取了名字。
的BarcodeMonitor
具有此方法:
public BlockingQueue<BarcodeData> GetQueue(Machines machine)
{
var processor = processors[machine];
return processor.Queue;
}
使得傳入的條形碼被放在正確的機器的隊列中。這工作正常。
條形碼在StartProccesingQueue()
(其中4個實例正在運行)中出列。在出隊方法,我有:
System.Console.WriteLine(string.Format("Thread {0} is taking from queue {1}", Thread.CurrentThread.Name, name));
Dequeue()
使用Monitor.Wait(_internalQueue)
當隊列是空的。 Enqueue()
使用Monitor.PulseAll(_internalQueue)
繼續等待出隊。
發生什麼情況是StartProccesingQueue()
方法從其他隊列中獲取,即使它只是訪問Queue
屬性,該屬性被分配了新的BlockingQueue
。事實上,到目前爲止,我只看到隊列「M」中的項目被採用,並且只有H1和H2線程正在執行它。
我真的不明白爲什麼會發生這種情況。
您正在訪問閉包中的foreach-iterator變量。這很危險,行爲依賴於編譯器。這可能是原因。只需做一個'var value = pair.Value;'並在lambda中使用,看看是否有幫助。 – Dirk 2015-02-06 12:27:53
@Dirk哇,這樣做。所有這一切都花了我的時間找到答案......作爲接受答案:) – Halfgaar 2015-02-06 12:38:43
它已經被回答了幾次,這只是一個不同的背景。我會發佈一個副本。 – Dirk 2015-02-06 12:39:26