Jakub
Jakub

Reputation: 195

C# Multiple Threads for work then wait until all finished

I'm working on the small SSHClient. I have a list of clients that are connected to different computers. I have a script that I want to run on those computers. I want to run it parallel in different threads. I got inspired here: Stackoverflow - threads

Here is my piece of code:

 int toProcess, count = 0;
        ManualResetEvent resetEvent = new ManualResetEvent(false);
        toProcess = count = clients.Count;
        for (int i = 0; i < count; i++)
        {
                new Thread(delegate()
                {
                    var cmd = clients[i].RunCommand("./script.sh");
                    res += cmd.Result;
                    if (Interlocked.Decrement(ref toProcess) == 0)
                        resetEvent.Set();
                }).Start();
        }
        resetEvent.WaitOne();

        //do something

To me this code looks OK. But sometimes (actually it's in most cases) it happens that after the program goes correctly out of for loop, it gets correctly to the line resetEvent.WaitOne(); but after, instead of waiting for all threads to finish and continue to proceed the rest of the code, it goes again to new Thread(delegate()... part of the code and since a variable i is already 2(in case there are two clients in the list of clients) I get an error:

Index was out of range. Must be non-negative and less than the size of the collection.

I wanted to ask how it is possible that it creates another thread although the for loop is finished. And how to avoid that?

Thank you

Upvotes: 2

Views: 591

Answers (2)

zahir
zahir

Reputation: 1432

You can use a parallel linq query and aggregate its results via Sum method:

var totalResult = (from i in Enumerable.Range(0, client.Count).AsParallel()
                   let cmd = clients[i].RunCommand("./script.sh")
                   select cmd.Result).Sum();

With AsParallel method we create as many threads as we can and with Sum method we run the linq query and fetch each result for summing them up

Upvotes: 0

Tudor
Tudor

Reputation: 62439

This is messy, in my opinion. I suggest using Parallel.For instead:

 int toProcess, count = 0;
 toProcess = count = clients.Count;
 object locker = new object();
 Parallel.For(0, count, i =>
 {
     var cmd = clients[i].RunCommand("./script.sh");
     lock(locker) res += cmd.Result;
 });

See this link: Parallel.For.

Upvotes: 3

Related Questions