Parallel.Foreach +收益回报? [英] Parallel.Foreach + yield return?
问题描述
我想用并行循环这样的处理的内容:
I want to process something using parallel loop like this :
public void FillLogs(IEnumerable<IComputer> computers)
{
Parallel.ForEach(computers, cpt=>
{
cpt.Logs = cpt.GetRawLogs().ToList();
});
}
好吧,它工作正常。但如何做,如果我想FillLogs方法返回一个IEnumerable
Ok, it works fine. But How to do if I want the FillLogs method return an IEnumerable ?
public IEnumerable<IComputer> FillLogs(IEnumerable<IComputer> computers)
{
Parallel.ForEach(computers, cpt=>
{
cpt.Logs = cpt.GetRawLogs().ToList();
yield return cpt // KO, don't work
});
}
修改
这似乎不是可能的...但我用这样的:
It seems not to be possible... but I use something like this :
public IEnumerable<IComputer> FillLogs(IEnumerable<IComputer> computers)
{
return computers.AsParallel().Select(cpt => cpt);
}
在这里我把 不过, .GetRawLogs()了ToList(); cpt.Logs = CPT
指令
推荐答案
短版 - 不,这不是个通过迭代器阻断T可能;较长的版本可能涉及同步队列/调用者的迭代器线程之间和平行工人(做排队)出队(做出队);但作为一个侧面说明 - 日志通常IO绑定,并parallelising东西都是IO的限制往往不能很好地工作。
Short version - no, that isn't possible via an iterator block; the longer version probably involves synchronized queue/dequeue between the caller's iterator thread (doing the dequeue) and the parallel workers (doing the enqueue); but as a side note - logs are usually IO-bound, and parallelising things that are IO-bound often doesn't work very well.
如果主叫方是要。需要一些时间来的消耗的每一个,那么可能会有一些好处,以一种方法,一次只能处理一个记录,但能做到这一点的,而来电消耗以前登录;也就是说,它的开始 工作
作为下一个项目在收益
,并为产量完成后等待
...但是,这是一次,相当复杂。作为一个简单的例子:
If the caller is going to take some time to consume each, then there may be some merit to an approach that only processes one log at a time, but can do that while the caller is consuming the previous log; i.e. it begins a Task
for the next item before the yield
, and waits for completion after the yield
... but that is again, pretty complex. As a simplified example:
static void Main()
{
foreach(string s in Get())
{
Console.WriteLine(s);
}
}
static IEnumerable<string> Get() {
var source = new[] {1, 2, 3, 4, 5};
Task<string> outstandingItem = null;
Func<object, string> transform = x => ProcessItem((int) x);
foreach(var item in source)
{
var tmp = outstandingItem;
// note: passed in as "state", not captured, so not a foreach/capture bug
outstandingItem = new Task<string>(transform, item);
outstandingItem.Start();
if (tmp != null) yield return tmp.Result;
}
if (outstandingItem != null) yield return outstandingItem.Result;
}
static string ProcessItem(int i)
{
return i.ToString();
}
这篇关于Parallel.Foreach +收益回报?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!