我遇到的情况是我正在运行一些需要几秒钟到几分钟的任务。我还有可能添加更多需要添加到已经运行的并行循环的数据。是否可以更新Parallel.For正在使用的当前集合并让它继续迭代,直到没有更多的对象要检索? 这里有一些示例代码显示了我的问题:
[Test]
public void DoesParallelForGetNewEntriesInLoop()
{
ConcurrentDictionary<int, string> dict = new ConcurrentDictionary<int, string>();
ConcurrentBag<string> bag = new ConcurrentBag<string>();
int i = 0;
// write to dictionary every 10ms simulating new additions
Timer t = new Timer(callback =>
{
dict.TryAdd(i++, "Value" + i);
}, dict, 0, 10);
// Add initial values
dict.TryAdd(i++, "Value" + i);
dict.TryAdd(i++, "Value" + i);
dict.TryAdd(i++, "Value" + i);
Parallel.For(0, dict.Count, (a, state) =>
{
string val = string.Empty;
if (dict.TryGetValue(a, out val))
{
bag.Add(val + Environment.NewLine);
}
if (i++ == 50)
state.Stop();
Thread.Sleep(5000);
});
foreach (var item in bag)
{
File.AppendAllText("parallelWrite.txt", item);
}
}
当我运行此结果时,我得到的结果就是:
Value2
Value1
Value3
Value4
有没有更好的方法去做我想在这里做的事情?
答案 0 :(得分:2)
如何在BlockingCollection
GetConsumingEnumerable()
并致电Parallel.ForEach
BlockingCollection<string> collection = new BlockingCollection<string>();
Parallel.ForEach(collection.GetConsumingEnumerable(), (x) => Console.WriteLine(x));
您可以使用BlockingCollection的Add()
方法将内容添加到集合中。
技术上有双重锁定&#34;自从Parallel.ForEach从可枚举到进程的块中取出块时锁定集合,并且构建BlockingCollection以支持多个使用者,因此它也实现了锁定。如果这成为性能问题(很可能),那么你可以为BlockingCollection实现自己的分区器,因为Parallel.ForEach具有接受OrderablePartitioner和Partitioner的重载。有一篇非常好的文章描述了这里的内容:http://blogs.msdn.com/b/pfxteam/archive/2010/04/06/9990420.aspx
答案 1 :(得分:0)
Parallel.For
中的from和to参数在循环开始之前只计算一次。
使用Parallel.ForEach
迭代新项目。
我不确定你想要实现什么,但更好的方法可能是将新数据放入堆栈/队列并定期弹出数据并处理它。