-1

If I used this code to create threads, how can I wait for all of these threads to complete before proceeding with the rest of the code? Or is there a different way to do this?

for(int i = 0; i < 25; i ++)
{             
   Program x = new Program(); // Make temporary
   Thread myThread = new Thread(() => x.doSomething(someParameter));
   myThread.Start();
}

I want to avoid making a big chunk of code for initializng, creating and joining threads.

Thread myThread1 = new Thread(() => x.doSomething(someParameter));
myThread1.Start();

Thread myThread2 = new Thread(() => x.doSomething(someParameter));
myThread2.Start();

Thread myThread3 = new Thread(() => x.doSomething(someParameter));
myThread3.Start();

myThread1.Join();
myThread2.Join();
myThread3.Join();

This code works but my goal is to avoid doing this 50-100 / n times depending on how many threads I need.

rogic
  • 13
  • 4

2 Answers2

0

The simplest solution is probably to put the threads into an array, then iterate over those threads to wait for all of them.

int numThreads = 25;
var threads = new Thread[numThreads];
for (int i = 0; i < numThreads; i++)
{
    Program x = new Program();
    Thread myThread = new Thread(() => x.doSomething(someParameter));
    myThread.Start();
    threads[i] = myThread;
}

foreach (var thread in threads)
{
    thread.Join();
}

That said, I'd recommend looking into whether tasks would work better than threads: threads are a bit more ... brute-force, though there are reasons to use them. I'd also look into the Parallel class, which lets you control the level of parallelism, if your threads can be run there (they probably can, but there may be reasons not to do so). In that case, you'd just do something like

Parallel.For(0, 25, i => { new Program().doSomething(someParameter); });    

... note that i is available inside the curly braces as the loop index; you could do something like new Program().doSomething(i); to pass a different parameter to each invocation of doSomething.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
minnmass
  • 251
  • 2
  • 7
0

An even better way is to use the Task Parallel Library (TPL).

int numTasks = 25;
var tasks = new Task[numTasks];
for (int i = 0; i < numTasks; i++)
{
    tasks[i] = Task.Run(() => new Program().doSomething(someParameter));
}
Task.WaitAll(tasks);

Starting a Thread consumes 1MB of RAM as is resource intensive. Tasks are managed better by the framework.

And, again, even better, you could do this:

var tasks =
    Enumerable
        .Range(0, numTasks)
        .Select(i => Task.Run(() => new Program().doSomething(someParameter)))
        .ToArray();
Task.WaitAll(tasks);

And possibly better again, you can await the whole lot:

async Task Main()
{
    var someParameter = new object();
    int numTasks = 25;
    var tasks =
        Enumerable
            .Range(0, numTasks)
            .Select(i => Task.Run(() => new Program().doSomething(someParameter)))
            .ToArray();
    await Task.WhenAll(tasks);
}
Enigmativity
  • 113,464
  • 11
  • 89
  • 172
  • I appreciate your responses so much! I tried the "threads into an array" first and that works! I do have a question, do you know why I have to initialize variables inside the for loop to pass the correct values? At first i was initializing them outside the loop and my threads were being passed wrong values. I'm going to try other ways you listed too! – rogic Oct 12 '22 at 06:12
  • 1
    Enigmativity the [`Task.Run`](https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.run) schedules work on the `ThreadPool`, and the `ThreadPool` creates only a limited number of threads immediately on demand. So starting 25 threads is not the same as scheduling 25 tasks with `Task.Run`. I would expect to see a significantly different behavior. – Theodor Zoulias Oct 12 '22 at 06:20
  • @TheodorZoulias Do you know how I can write to the same file from these threads. My goal is for each thread to write a line to a LOG file, I have a function that deals with writing to file however when the threads call this line at the same time i have an IO error, "this file is already used by a different process". Is writing to the same file at the same time something that's doable? – rogic Oct 12 '22 at 06:28
  • @rogic search for "C# write to file from multiple threads", and you'll find lots of relevant questions. If none of them is exactly what you want to know, you could ask a new question. – Theodor Zoulias Oct 12 '22 at 06:31
  • @TheodorZoulias i tried searching for that earlier but couldn't find anything that worked. I'll keep searching more before posting a new question. – rogic Oct 12 '22 at 06:47
  • @rogic - When creating tasks or threads they take time to get started. Meanwhile your loop is well and truly finished - so when the task/thread reads the local value it gets the value from the end of the loop. – Enigmativity Oct 12 '22 at 10:22