class MultiThreadRunner { static object workerLocker = new object(); static int runningWorkers = 0; /// <summary> /// The delegate is to be used as a placeholder for a parameterless method to invoke /// </summary> public delegate void ParameterlessMethodDelegate(); /// <summary> /// An overload to Run method, set the concurrentNoOfInstances to a default no /// </summary> /// <param name="myMethod">The method to be invoke, passed as a delegate</param> /// <param name="noOfInvocations">Total no of invocations to execute</param> public void Run(Delegate myMethod, int noOfInvocations) { this.Run(myMethod, noOfInvocations, 0); } /// <summary> /// The method will submit the method into the ThreadPool /// </summary> /// <param name="myMethod">The method to be invoke, passed as a delegate</param> /// <param name="noOfInvocations">Total no of invocations to execute</param> /// <param name="concurrentNoOfInstances">Concurrent no of instances -> ThreadPool.MinThreads</param> public void Run(Delegate myMethod, int noOfInvocations, int concurrentNoOfInstances) { int iRow = runningWorkers = noOfInvocations; int iStartWorker, iEndWorker, iCompletion; // Adjust the min threads SetMinThreads(concurrentNoOfInstances); ThreadPool.GetAvailableThreads(out iStartWorker, out iCompletion); Debug.WriteLine(string.Format("Available Threads, Start : {0}", iStartWorker)); for (int i = 1; i <= iRow; i++) { ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(InvokeMethod), myMethod); Debug.WriteLine("Submitted a queue : " + i.ToString()); } lock (workerLocker) { while (runningWorkers > 0) Monitor.Wait(workerLocker); } ThreadPool.GetAvailableThreads(out iEndWorker, out iCompletion); Debug.WriteLine(string.Format("All threads have been completed, Start : {0} - End : {1} - Completion : {2}", iStartWorker, iEndWorker, iCompletion)); } /// <summary> /// Set the ThreadPool Mininum Threads, this is to avoid a delay bottleneck, please refer to http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx /// </summary> /// <param name="concurrentNoOfInstances"></param> private void SetMinThreads(int concurrentNoOfInstances) { int iMaxWorker, iMinWorker, iCompletion; ThreadPool.GetMaxThreads(out iMaxWorker, out iCompletion); ThreadPool.GetMinThreads(out iMinWorker, out iCompletion); if (concurrentNoOfInstances != 0) { if (concurrentNoOfInstances > iMaxWorker) { ThreadPool.SetMinThreads(iMaxWorker, iCompletion); Debug.WriteLine("The requested concurrent no of instances is higher than max threads, set the min threads as max threads : " + iMaxWorker); } else { ThreadPool.SetMinThreads(concurrentNoOfInstances, iCompletion); Debug.WriteLine("Set the min threads to " + concurrentNoOfInstances); } } else { Debug.WriteLine("Using the default min threads : " + iMinWorker); } } /// <summary> /// To invoke the method /// </summary> /// <param name="myMethod"></param> private void InvokeMethod(object myMethod) { Debug.WriteLine("Invoke the method in thread : " + Thread.CurrentThread.ManagedThreadId); ((Delegate)myMethod).DynamicInvoke(null); lock (workerLocker) { runningWorkers--; Monitor.Pulse(workerLocker); } } } |
2 comments:
really good work!
Excellent Passing methods. The example given in the Article is really interesting. Thanks for sharing such nice example here in this site.
r4 revolution