5
    private void button1_Click(object sender, EventArgs e)
    {
        for (int i = 0; i < 15; i++)
        {
            Thread nova = new Thread(Method);
            nova.Start();
        }
        listBox1.Items.Add("Some text");
    }

    private void Method()
    {
        for (int i = 0; i < 15; i++)
        {
            Console.WriteLine(i);
        }

    }

This code does write: Some text and then numbers 111222333..... I would like that it writes 111122223333.... and then on the end Some text. is it possible to do that with threads (parent thread wait for child threads)? or do i have to use something else?

Car90
  • 65
  • 1
  • 1
  • 4
  • Why are you using threads for this? I assume this is a contrived example, but I need more information to give you an accurate answer. – Matthew Brubaker Jun 22 '12 at 16:10
  • possible duplicate of [C#: Waiting for all threads to complete](http://stackoverflow.com/questions/263116/c-waiting-for-all-threads-to-complete) – Alan Jun 22 '12 at 16:13
  • No this is just an example. i need to access unknown number of web pages. and all of them read same info and store it in database. so when all threads are finished i need to do something with that info. i can't do anything until i have all the info i needed – Car90 Jun 22 '12 at 16:14

4 Answers4

16

You need to keep track of all the threads, and use Thread.Join on each one. This waits until the specified thread terminates, and then continues executing. Like this:

var threads = new List<Thread>();
for (int i = 0; i < 15; i++)
{
    Thread nova = new Thread(Method);
    nova.Start();
    threads.Add(nova);
}
foreach (var thread in threads)
    thread.Join();
listBox1.Items.Add("Some text");
Roman Starkov
  • 59,298
  • 38
  • 251
  • 324
10

I suggest to use TPL to get this done. You won't need to spawn so many threads. By default TPL will use thread pool for that:

using System;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        private const int TaskCount = 15;

        static void Main(string[] args)
        {
            var tasks = new Task[TaskCount];
            for (var index = 0; index < TaskCount; index++)
            {
                tasks[index] = Task.Factory.StartNew(Method);
            }
            Task.WaitAll(tasks);

            Console.WriteLine("Some text");
        }

        private static void Method()
        {
            for (int i = 0; i < 15; i++)
            {
                Console.WriteLine(i);
            }
        }
    }
}
Sergei B.
  • 3,227
  • 19
  • 18
1

You could have two threads, the 2nd one waiting on a signal to fire from the first.

private void Foo()
{
  var signals = new List<ManualResetEvent>();

  for (int i = 0; i < 15; i++)
  {
    var signal = new ManualResetEvent(false);
    signals.Add(signal);
    var thread = new Thread(() => { Method(); signal.Set(); });
    thread.Start();
  }

  var completionTask = new Thread(() =>
  {
    WaitHandle.WaitAll(signals.ToArray());
    CompletionWork();
  });
  completionTask.Start();

}

private void Method()
{
}

private void CompletionWork()
{
}

The better solution now with .Net 4.0 (and later) is to use Tasks, and invoke a method using ContinueWith

private void Foo()
{
  var childThreads = new List<Task>();
  for (int i = 0; i < 15; i++)
  {
    var task = new Task(Method);
    task.Start();
    childThreads.Add(task);
  }

  var completionTask = new Task(() => 
  { 
    Task.WaitAll(childThreads.ToArray());
  }).ContinueWith(t => CompletionWork());

}

private void Method()
{
}

private void CompletionWork()
{
}

The join answers also work, but require the containing thread to block. If you don't want the GUI to block, Spawn an additional thread around the 1st.

payo
  • 4,501
  • 1
  • 24
  • 32
0

You can use thread.join to wait for threads to end. See http://www.dotnetperls.com/thread-join for an page on how to use it.

Andrew Cox
  • 10,672
  • 3
  • 33
  • 38