我们有一个 ConcurrentQueue 用于在 3 个线程之间共享数据。线程 A 不断地用数据填充队列。线程 B 旨在将这些数据记录到文件中。线程 C 应该检索队列中最年轻的条目(或尽可能接近最年轻的条目),对其执行一些操作并在屏幕上显示结果。
线程 B,为了及时对文件写入操作进行集群,执行如下操作:
if (cq.Count > 100)
{
while (cq.Count > 1)
{
qElement = PopFromCq(cq); // PopFromCq uses cq.TryDequeue()
bw.Write(qElement.data); // bw is a binary writer
}
}
else
{
System.Threading.Thread.Sleep(10);
}
即,它等待至少 100 个元素排队,然后将它们写入磁盘。它总是在队列中维护至少一项,原因是我们希望线程 C 始终可以访问至少一项。
线程 C 中的循环如下所示:
while (threadsRunning)
{
System.Threading.Thread.Sleep(500); // Update twice per second
ProcessDataAndUpdateScreen(cq.ElementAt(cq.Count - 1)); // our terrible attempt at looking at the latest (or close to latest) entry in the queue
}
在这个循环中,由于将数据写入磁盘的线程与 cq.ElementAt(cq.Count-1) 调用之间的竞争,我们有时会遇到异常。我相信正在发生的事情如下:
- cq.Count 被计算为,比如 90。
- 到那时,线程 B 已经开始了它的循环,它正在从队列中取出数据以写入磁盘
- 在调用 cq.ElementAt() 时,线程 B 消耗了许多项目,使得 (cq.Count - 1) 不再指向队列中的有效条目。
关于在队列上运行多个线程的情况下访问队列中最年轻条目的好方法的任何想法?
问候,