如何制作IEnumerable方法的并行方法

Flo*_*ian 9 c# parallel-processing nested-loops

在这篇文章之后,我想要并行化这个方法:

    public IEnumerable<string> GetAllLogs(IEnumerable<IComputer> computers)
    {
        foreach (var cpt in computers)
        {
            foreach (var log in cpt.GetLogs())
            {
                yield return log;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

当其中一个方法GetLogs完成时,我希望方法"yield returns"成为日志.如果我有4台电脑返回:

  • 计算机01:"a","b","c","d","e"
  • 计算机02:"1","2","3","4","5"
  • 计算机03:"alpha","beta","gamma","delta","epsilon"
  • 计算机04:"我","II","III","IV","V"

使用"顺序方法",输出为:

a
b
c
d
e
1
2
3
4
5
alpha
beta
gamma
delta
epsilon
I
II
III
IV
V
Run Code Online (Sandbox Code Playgroud)

这些方法在20秒内运行.有一个Thread.Sleep(1000)GetLogs方法.

我希望输出看起来像这样:

III
a
4
gamma
b
c
IV
5
d
II
beta
e
1
2
delta
alpha
3
epsilon
I
Run Code Online (Sandbox Code Playgroud)

并在几秒钟内运行.

我想方法返回一个IEnumerable

Geo*_*dze 17

这就是你需要的:

public IEnumerable<string> GetAllLogsParallel(IEnumerable<IComputer> computers)
{
    return computers
        .AsParallel()
        .SelectMany(cpt => cpt.GetLogs());
}
Run Code Online (Sandbox Code Playgroud)

如果你想同时开始处理4- computers,你可以像这样调整并行度:

public IEnumerable<string> GetAllLogsParallel(IEnumerable<IComputer> computers)
{
    return computers
        .AsParallel()
        .WithDegreeOfParallelism(4)
        .SelectMany(cpt => cpt.GetLogs());
}
Run Code Online (Sandbox Code Playgroud)

以下是仅供理解的简化说明.要了解更多信息,请访问MSDN上的PLINQ(Parallel LINQ).

好吧,.AsParallel()- 将computers可枚举分成4个部分,同时启动4个线程.每个线程执行cpt.GetLogs()的每一个computer.结果是IEnumerable<IEnumerable<string>>- 可枚举的枚举数.SelectMany()用于通过连接内部枚举和消除外部枚举来展平此列表.结果按照到达顺序自动合并到主线程中.

  • @FelixK.该方法的返回值是可枚举的,而不是`GetLogs`返回的值.该方法立即返回.迭代后,可以通过枚举查询和返回值. (2认同)