Join does not dictate that the threads are run sequentially — it merely makes the current thread wait for the specified thread to finish before continuing.
So if you start 300 threads and then join them all, the 300 threads will run in parallel and the joining thread will complete once the 300 threads are finished.
const int COUNT = 300;
// create and start the threads
var threads = new Thread[COUNT];
for (int index = 0; index < COUNT; index += 1)
{
threads[index] = new Thread(...);
threads[index].Start();
}
// now they're running, join them all
for (int index = 0; index < COUNT; index += 1)
{
threads[index].Join();
}
// we're done
The important part is that you start them all before you start joining, otherwise you will wait for each thread to finish before starting the next, thus then they really would be sequential. I guess this is what you may be doing?