Adhil
Adhil

Reputation: 1858

How to start a thread within another thread

I am exploring with the concept of starting a thread within another thread. this is the code I have come up with, this is watered down version of another program which I am developing currently however I found out that the second level of threads do not complete successfully.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;

namespace ConsoleApplication4
{
    public class SomeClassA
    {
        public SomeClassA(string display)
        {
            System.Threading.Thread.Sleep(1000);
            Console.WriteLine(display);
        }
    }

    public class MainSomeClassA
    {
        public List<SomeClassA> SomeClassaAList;
        public List<Thread> ThreadList;
        public MainSomeClassA()
        {
            ThreadList = new List<Thread>();
            SomeClassaAList = new List<SomeClassA>();
            for (int i = 0; i < 10; i++)
            {
                ThreadList.Add(new Thread(() => StartThread("Hello")));
            }
            WaitComplete();
        }
        public void WaitComplete()
        {
            bool AllThreadsAlive = true;
            while (AllThreadsAlive)
            {
                AllThreadsAlive = false;
                foreach (Thread t in ThreadList)
                {
                    if (t.IsAlive)
                    {
                        AllThreadsAlive = true;
                    }
                }
            }
        }
        public void StartThread(string display)
        {
            SomeClassaAList.Add(new SomeClassA(display));
        }
    }

    class Program
    {
        public static List<MainSomeClassA> MainSomeClassAList = new List<MainSomeClassA>();
        static void Main(string[] args)
        {

            Stopwatch sw = new Stopwatch();
            MainSomeClassAList = new List<MainSomeClassA>();
            List<Thread> ThreadList = new List<Thread>();
            bool threadsAlive = true;
            sw.Reset();
            sw.Start();
            for (int i = 0; i < 10; i++)
            {
                Thread t = new Thread(AddToMainClassAList);
                t.Start();
                ThreadList.Add(t);
            }
            while (threadsAlive)
            {
                threadsAlive = false;
                foreach (Thread t in ThreadList)
                {
                    if (t.IsAlive)
                    {
                        threadsAlive = true;
                    }
                }
            }
            sw.Stop();
            Console.WriteLine("Elapsed Time: {0}", sw.ElapsedMilliseconds);
            Console.ReadKey();
        }

        public static void AddToMainClassAList()
        {
            MainSomeClassAList.Add(new MainSomeClassA());
        }

    }
}

The above code does not print out "hello" and exits without creating the SomeClassA List.

Upvotes: 0

Views: 1236

Answers (1)

Peter Duniho
Peter Duniho

Reputation: 70652

The problem with your code is that you never start the inner threads. Change you constructor to look like this, and it will work:

public MainSomeClassA()
{
    ThreadList = new List<Thread>();
    SomeClassaAList = new List<SomeClassA>();
    for (int i = 0; i < 10; i++)
    {
        ThreadList.Add(new Thread(() => StartThread("Hello")));
        // Start thread here:
        ThreadList[ThreadList.Count - 1].Start();
    }
    WaitComplete();
}

That said, I should point out that you're lucky the program doesn't crash. You have ten threads concurrently trying to modify the MainSomeClassAList object, some of which will necessarily force a reallocation of the internal buffer. As it is, if you print out the Count of the list at the end, you will find it isn't always 10 as it ought to be.

For the code to be truly correct, you would need to add synchronization around the call to Add() in the AddToMainClassAList() method. Same thing applies to the StartThread() method and the SomeClassaAList object.

Finally, your method for waiting on the threads is very poor. You should try to avoid polling at all costs. In this case, the Thread.Join() method is a reasonable choice (you should try to avoid blocking a thread at all, but for this example, it's unavoidable). For example, your busy loop can be replaced by this:

foreach (Thread thread in ThreadList)
{
    thread.Join();
}

Upvotes: 1

Related Questions