Connecting Tech Pros Worldwide Forums | Help | Site Map

Worker threads finish before main thread does??

Newbie
 
Join Date: Mar 2007
Posts: 15
#1: Oct 11 '07
Hello,

I've written a simple app as a test to run multiple threads from a pool. I'm able to do this, but what's happening is that the main thread finishes before all the workers do. So the Console shows:
"Main thread exits." in between the worker thread strings.

Can anyone see what I'm doing wrong please?

Thanks in Advance!

Here's my code:

Expand|Select|Wrap|Line Numbers
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Threading;
  5. using System.Reflection;
  6.  
  7. namespace ThreadPool2
  8. {
  9.    public static class Example
  10.    {      
  11.       private static int _MaxThreads=2;
  12.       private static ManualResetEvent _DoneEvent;
  13.  
  14.       public static void Main()
  15.       {
  16.          // One event is used for each Method object
  17.          ManualResetEvent[] aDoneEvents = new ManualResetEvent[3];
  18.  
  19.          Type aTestClass = typeof(Tests);
  20.  
  21.          ThreadPool.SetMaxThreads(_MaxThreads, _MaxThreads);
  22.  
  23.          MethodInfo[] aMethods = aTestClass.GetMethods();
  24.          int i = 0;
  25.          foreach(MethodInfo aMethod in aMethods)
  26.             if(aMethod.ReturnType.Name == "Void")
  27.             {               
  28.                aDoneEvents[i] = new ManualResetEvent(false);
  29.                _DoneEvent = aDoneEvents[i];
  30.                ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc), aMethod);
  31.  
  32.                i++;               
  33.             }
  34.  
  35.          WaitHandle.WaitAll(aDoneEvents); //code gets stuck here but I can't see why!
  36.  
  37.          Console.WriteLine("Main thread exits.");
  38.          Console.Read();
  39.       }//Main
  40.  
  41.       // This thread procedure performs the task.
  42.       static void ThreadProc(Object stateInfo)
  43.       {
  44.          object[] aObj = null;
  45.  
  46.          Tests aTests = new Tests(_DoneEvent);
  47.  
  48.          MethodInfo aMethod = stateInfo as MethodInfo;
  49.  
  50.          aMethod.Invoke(aTests, aObj);
  51.  
  52.          aTests.DoneEvent.Set();
  53.  
  54.       }//ThreadProc
  55.    }
  56. }
  57.  
  58.  
  59.  
  60. using System;
  61. using System.Collections.Generic;
  62. using System.Text;
  63. using System.Threading;
  64.  
  65. namespace ThreadPool2
  66. {
  67.    public class Tests
  68.    {
  69.       public ManualResetEvent DoneEvent;
  70.  
  71.       public Tests(ManualResetEvent theDoneEvent)
  72.       {
  73.          DoneEvent = theDoneEvent;
  74.       }
  75.  
  76.  
  77.       public void Test1()
  78.       {
  79.          Console.WriteLine("This is Test 1 Start...");
  80.          Thread.Sleep(2000);
  81.          Console.WriteLine("This is Test 1 Stop...");
  82.  
  83.       }
  84.  
  85.       public void Test2()
  86.       {
  87.  
  88.          Console.WriteLine("This is Test 2 Start...");
  89.          Thread.Sleep(2000);
  90.          Console.WriteLine("This is Test 2 Stop...");
  91.  
  92.        }
  93.  
  94.       public void Test3()
  95.       {
  96.  
  97.          Console.WriteLine("This is Test 3 Start...");
  98.          Thread.Sleep(2000);
  99.          Console.WriteLine("This is Test 3 Stop...");
  100.  
  101.       }
  102.  
  103.    }
  104. }
  105.  
  106.  
  107.  
  108.  
  109.  

Newbie
 
Join Date: Mar 2007
Posts: 15
#2: Oct 12 '07

re: Worker threads finish before main thread does??


I should have realized how sensitive threads are to timing.
Instead of having aglobal DoneEvents, I need to pass it within this loop immediately because by the time I access it beyond here, it wouls have gotten out of synch. So I bundled that data for my callback into a lightweight class that takes the doevents and the method from within the loop and passes it to my worker method.

The gist of the fix is as follows.

class bundleddata
{
MethodInfo Method;
ManualResetEvent MRE;
}

...

MethodInfo[] aMethods = aTestClass.GetMethods();
int i = 0;
foreach(MethodInfo aMethod in aMethods)
if(aMethod.ReturnType.Name == "Void")
{
bundleddata aBD=new bundleddata();
aDoneEvents[i] = new ManualResetEvent(false);
aBD.Method=aMethod ;
aBD.MRE = aDoneEvents[i];
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc), aBD);

i++;
}
Reply


Similar .NET Framework bytes