我有一个使用多层生产者 - 消费者模式构建的复杂应用程序,多个消费者在将数据排入下一组消费者之前执行专门任务。该应用程序的最终工作是将原始数据文件分解为已经规范化的各个单元的测试记录。
P-C模式的基础使用来自http://dustin-hyun.blogspot.com/2013_07_01_archive.html的Dustin Hyun模式。由于采用了多层次方法和其他方法,我做了很多修改。代码太复杂了,无法在此处发布 - 也许我可以根据请求发布片段以帮助澄清和回答问题。
我使用了两种工具来加速文件的处理速度。首先是任何一级消费者的多个实例 - 可能有八个“索引”消费者正在运行,他们的工作是将测试数据从单位ID和测试名称转换为单位指数和测试名称指数,以将结果标准化以加载到D B。其次是在操作的两个点将单元捆绑到合并的DataTable中。
我已经确定数据会间歇性地丢失,但是会以相当可预测的模式丢失。它似乎是数据预期的最后一个不完整的捆绑包。在标准循环模式之后,我检查了一个布尔值,我用它来标记是否有一个incoMplete包,它可以工作:
if (dataToSend) // Check if incomplete bundle to process & send prior to ending comsumer operation.
{
UpdateLimitsIndices(bundleNlu);
Enqueue(StdfQType.Func, new BundledNamedTables((N_ParamRes)bundlePR.Copy(), (N_FuncRes)bundleFR.Copy(), numUnitsInCurrBundle));
}
我也把锁放到我能看到的任何地方,任何p_c实体从任何共享队列成员读取或写入任何内容。只有锁,似乎没有真正的影响。一时兴起,我开始在循环重新旋转之前播放睡眠时间到目前为止,导致数据丢失1ms睡眠的测试条件在100 ms睡眠期间甚至在有限测试期间甚至10 ms睡眠时都不会导致数据丢失。可能是因为较长的睡眠允许正确处理最后一块/数据包吗?
我认识到这个问题含糊不清,细节很少,因为申请过于复杂而无法发布。但是,我希望我能够提供足够的信息来启动对话框。我想找到你的想法。
杰夫
答案 0 :(得分:1)
我建议,因为你没有使用线程安全的集合(并且你的代码也没有使用的作者),这可能是由于并发写入操作失败而导致数据丢失的基础(无声)
幸运的是,与任务并行库(TPL)一起,.NET 4.0为我们提供了一大堆并发集合,这些集合对于多线程环境来说是线程安全的。
查看System.Collections.Concurrent中的集合,因为它们都是线程安全的,并且它们的锁定机制比传统的基于lock
的对象快得多。
答案 1 :(得分:0)
线程很难做到正确,看起来你没有做对。另外,为什么你(以及该博客文章的作者)使用睡眠间隔而不是Monitor.Pulse()
?
为什么不使用一个能够在底层线程协调机制之上提供稍高抽象级别的库,而不是试图自己实现呢?