Flo*_*ian 25 c# yield-return parallel.foreach
我想用这样的并行循环处理一些东西:
public void FillLogs(IEnumerable<IComputer> computers)
{
Parallel.ForEach(computers, cpt=>
{
cpt.Logs = cpt.GetRawLogs().ToList();
});
}
Run Code Online (Sandbox Code Playgroud)
好的,它工作正常.但是如果我想让FillLogs方法返回一个IEnumerable怎么办?
public IEnumerable<IComputer> FillLogs(IEnumerable<IComputer> computers)
{
Parallel.ForEach(computers, cpt=>
{
cpt.Logs = cpt.GetRawLogs().ToList();
yield return cpt // KO, don't work
});
}
Run Code Online (Sandbox Code Playgroud)
编辑
似乎不可能......但我使用这样的东西:
public IEnumerable<IComputer> FillLogs(IEnumerable<IComputer> computers)
{
return computers.AsParallel().Select(cpt => cpt);
}
Run Code Online (Sandbox Code Playgroud)
但是我把cpt.Logs = cpt.GetRawLogs().ToList();指示放在哪里
Mar*_*ell 14
短版本 - 不,这是通过迭代器块无法实现的; 较长的版本可能涉及调用者的迭代器线程(执行dequeue)和并行工作者(执行enqueue)之间的同步队列/出队; 但是作为旁注 - 日志通常是IO绑定的,并且对IO绑定的东西进行并行化通常不能很好地工作.
如果调用者需要花费一些时间来消耗每个,那么一次只处理一个日志的方法可能有一些优点,但是当调用者使用前一个日志时可以这样做; 也就是说,它开始一个Task 下一个项目之前yield,和之后的等待完成yield...但是,这又是,相当复杂.作为简化示例:
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();
}
Run Code Online (Sandbox Code Playgroud)
我不想冒犯,但也许缺乏理解。Parallel.ForEach意味着TPL将根据可用硬件在多个线程中运行foreach。但这意味着,ii 可以并行完成这项工作!yield return让您有机会从列表(或任何其他)中获取一些值,并在需要时将它们一一返回。它无需首先查找与条件匹配的所有项目,然后迭代它们。这确实是性能优势,但无法并行完成。
| 归档时间: |
|
| 查看次数: |
11824 次 |
| 最近记录: |