views:

107

answers:

6

Hi I have two method calls that I want to call using two threads. Then I want them to wait till method executions get completed before continuing. My sample solution is something like below.

    public static void Main()
    {   
        Console.WriteLine("Main thread starting.");
        String[] strThreads = new String[] { "one", "two" };

        String ctemp = string.Empty;
        foreach (String c in strThreads)
        {
            ctemp = c;
            Thread thread = new Thread(delegate() { MethodCall(ctemp); });
            thread.Start();
            thread.Join();
        }

        Console.WriteLine("Main thread ending.");
        Console.Read();
    }


    public static void MethodCalls(string number)
    {
        Console.WriteLine("Method call " + number);
    }

Is this will do the job? Or is there another better way to do the same thing?

+1  A: 

This sequence of statements...:

        Thread thread = new Thread(delegate() { MethodCall(ctemp); });
        thread.Start();
        thread.Join();

is equivalent to just calling the method directly -- since you're waiting for the new thread to finish right after starting it, there's no benefit from threading! You need to first start all threads in a loop (put them in an array list or some similar container), then join them in a separate loop, to get concurrent execution of the methods.

Alex Martelli
Again why are you rolling a thread for this when you have a perfectly good thread pool.
csaam
A: 

If you intended for your two threads to execute one after the other, then yes, the above code will suffice (though my C# syntax knowledge is a little fuzzy off the top of my head so I can't say if the above compiles nicely or not), but why use threads if you want ordered, synchronous execution?

If instead what you want is for the two method calls to execute in parallel, you need to take the thread.Join(); out of the for-loop (you'll need to hang on to the thread objects, likely in an array.)

Joshua Barron
+1  A: 

What you're doing ther eis creating a thread and then waiting to finish, one by one. You have, at any time, at most two thread running: the main and the one started.

What you want is to start all threads, then wait for all to complete:

public static void Main()
{   
    Console.WriteLine("Main thread starting.");
    String[] strThreads = new String[] { "one", "two" };

    int threadCount = strThreads.Length;
    AutoResetEvent eventdone = new AutoResetEvent(false);

    String ctemp = string.Empty;
    foreach (String c in strThreads)
    {
        ctemp = c;
        Thread thread = new Thread(delegate() { 
            try
            {
               MethodCall(ctemp); 
            }
            finally 
            {
               if (0 == Interlocked.Decrement(ref threadCount) 
               {
                  eventDone.Set();
               }
            }
        });
        thread.Start();
    }

    eventDone.WaitOne();

    Console.WriteLine("Main thread ending.");
    Console.Read();
}


public static void MethodCalls(string number)
{
    Console.WriteLine("Method call " + number);
}
Remus Rusanu
Why the downvote?
Jay Riggs
Probably a hater, +1 from me.
Lirik
Btw, I totally agree with Jay about using the ThreadPool. But I disagree about using WaitAll, for the 64 handles limit if nothing else.
Remus Rusanu
It's to complicated. Use the thread pool.
csaam
+3  A: 

I'd look into running your method via ThreadPool.QueueUserWorkItem and then using WaitHandle.WaitAll to wait for all of them to complete.

Jay Riggs
+1, spinning up a dedicated thread and waiting for it to complete it typically not the best idea. Aside from the startup costs, it makes it difficult to control the number of concurrently executing tasks. The Task API in .NET 4 is even better for this.
Josh Einstein
Why would you even consider QeueuUserWorkItem when a delegate can do the same thing in a type safe manner. WaitHandle.WaitAll will not allow you to hanfle exceptions.
csaam
A: 

Take a look at BackgroundWorker Component; I beleive it works with Windows Forms, WPF and Silverlight, basically somewhere UI is involved

Khurram Aziz
A: 

This is the 2nd time this week I've seen this question. The second loop should have an internal try catch block for logging or otherwise handling exceptions. I'm sure you can figure that part out. Most devs don't realise that BeginInvoke returns an IAsyncResult.

Action<string> action = MethodCalls;
List<IAsyncResult> results = new List<IAsyncResult>();
foreach (String c in strThreads) 
{
    results.Add(action.BeginInvoke());
}
foreach(IAsyncResult result in results)
{
   action.EndInvoke(result);
}
csaam