【发布时间】:2012-12-04 10:36:24
【问题描述】:
我对传递到广播块的列表集合有疑问。这是我到目前为止所拥有的(伪代码,因为完整的代码库太长了):
private BroadcastBlock<List<Quote>> tempBCB;
private TransformBlock<List<Quote>, Dictionary<int, IParentOrder>> tfb1;
private TransformBlock<List<Quote>, Dictionary<int, IParentOrder>> tfb2;
private BatchBlock<Dictionary<int, IParentOrder>> batchBlock;
private JoinBlock<List<Quote>, Dictionary<int, IParentOrder>[]> joinBlock;
private TransformBlock<Tuple<List<Quote>,
Dictionary<int, IParentOrder>[]>,List<MySignal>> transformBlock;
tempBCB = new BroadcastBlock<List<Quote>>(quoteList => {
return quoteList;
//return Cloning.CloneListCloneValues<Quote>(quoteList);
});
tfb1 = new TransformBlock<List<Quote>, Dictionary<int, IParentOrder>>(
quotes => {//do something and return Dictionary<int, IParentOrder>});
tfb2 = new TransformBlock<List<Quote>, Dictionary<int, IParentOrder>>(
quotes => {//do something and return Dictionary<int, IParentOrder>});
batchBlock = new BatchBlock<Dictionary<int, IParentOrder>>(2);
joinBlock = new JoinBlock<List<Quote>, Dictionary<int, IParentOrder>[]>(
new GroupingDataflowBlockOptions { Greedy = false });
transformBlock = new TransformBlock<Tuple<List<Quote>,
Dictionary<int, IParentOrder>[]>, List<MySignal>>(
tuple => { //do something and return List<MySignal>;});
//Linking
tempBCB.LinkTo(tfb1);
tempBCB.LinkTo(tfb2);
tfb1.LinkTo(batchBlock);
tfb2.LinkTo(batchBlock);
tempBCB.LinkTo(joinBlock.Target1);
batchBlock.LinkTo(joinBlock.Target2);
joinBlock.LinkTo(transformBlock);
我的问题是,在tempBCB 的当前实现中,我在最终的TransformBlock<TInput, TOutput> 中得到了奇怪的结果。
例如,作为元组一部分的Dictionary<int, IParentrOrder> 集合大小不相等,即使tfb1 和tfb2 的实现100% 相同。
tempBCB 实现中注释掉的行对广播列表进行了深层复制,这似乎确实解决了问题,但问题是这种深层复制使我的代码慢了大约 10 倍,这是在这样的我需要找到不同的解决方案。
首先,我不确定这是问题所在,还是只是速度变慢导致并发操作按预期执行,即使错误仍然隐藏在那里。
其次,如果广播块中缺少深拷贝会导致这些问题,我怎样才能让它更快?
这是我的深拷贝代码:
public static List<TValue> CloneListCloneValues<TValue>(List<TValue> original)
where TValue : ICloneable
{
List<TValue> ret = new List<TValue>(original.Count);
foreach (TValue entry in original)
{
ret.Add((TValue)entry.Clone());
}
return ret;
}
我可能会将Quote[] 而不是List<Quote> 输入广播块,但我看不出它如何有助于加快深度复制的性能。
我的问题是:
- 深拷贝问题是否是真正的问题(我怀疑是因为
List<Quote>,流入广播块从未被任何转换块改变)? - 如果是,为什么以及如何提高深层复制的效率?
【问题讨论】:
-
你能创建一个独立的、完整的代码示例来展示这种行为吗?我想说问题在于副本,您无法绕过它(但这取决于您的示例将表现出的行为),但我无法用上面阅读的内容复制该行为。跨度>
-
另外,您为什么不期望
tfb1和tfb2不会返回不同的结果?如果您有单独的转换块,那么我希望它们会做不同的事情。 -
@casperOne,将很快发布一个独立的代码示例。我希望得到相同的结果,因为这些块生成完全相同的数据,但我将使用相同的 Func 初始化这些块以使其更清晰
-
我认为在这种情况下,您需要弄清楚为什么对于可能相同的输入会得到不同的结果。盲目地尝试一些东西(比如你的深拷贝)很可能只会隐藏错误,它并不能解决它。
-
@svick,同意,我被其他工作耽搁了,我将很快发布完整代码的重新工作,如果您也可以快速查看它,我将不胜感激。从第一次测试中,我注意到我肯定遇到的一个问题是,当 joinBlock 处于非贪婪模式时,broadCastBlock 将项目发送到 joinBlock,很可能在 joinBlock 等待来自另一个 targetBlock 的项目时导致项目下降。 “手动” SendAsync() 解决了该问题,但由于结构相当复杂,可能存在更多问题。
标签: c# collections concurrency cloning tpl-dataflow