Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a IEnumerable method parallel method

Following to this post, I want parallelize this method :

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

I want the method "yield returns" a log when one of the method GetLogs is finished. If I have 4 computers which returns :

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

With the "sequential method", the output is :

a
b
c
d
e
1
2
3
4
5
alpha
beta
gamma
delta
epsilon
I
II
III
IV
V

And the methods runs in 20 seconds. there is a Thread.Sleep(1000) in the GetLogs method.

I want the output looks like this :

III
a
4
gamma
b
c
IV
5
d
II
beta
e
1
2
delta
alpha
3
epsilon
I

and runs in few seconds.

I want to the methods returns an IEnumerable

like image 301
Florian Avatar asked Nov 24 '11 14:11

Florian


1 Answers

This is what you need:

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

If you want to start processing of 4 computer-s at the same time you can adjust the degree of parallelism like this:

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

Following is a simplified explanation just for understanding. To learn more about that just visit PLINQ (Parallel LINQ) at MSDN.

Well, .AsParallel() - splits the computers enumerable into 4 parts and starts 4 threads at the same time. Each thread executes cpt.GetLogs() for each computer. The result is IEnumerable<IEnumerable<string>> - enumerable of enumerables. SelectMany() is used to flatten this list by concatenating inner enumerables and eliminating outer ones. Results are merged back automatically into the main thread in the order of their arrival.

like image 111
George Mamaladze Avatar answered Oct 05 '22 01:10

George Mamaladze