Showing posts with label Delegate. Show all posts
Showing posts with label Delegate. Show all posts

Thursday, June 26, 2008

Testing Concurrency using ThreadPool (Multithread)

There are times when we need to test our code in concurrent manner where there are some numbers of instances running simultaneously.

Concurrency

This is different with the invocation such as below code where the method will be executed in sequential manner, this kind of test may be useful to test how long it may take to execute the method.

for (int iTest = 0; iTest < 100; iTest++)
{
    TestingMethodA();
}

 

For this testing concurrency, I’m using Joseph Albahari’s Threading in C# articles in ThreadPooling section as references to the MultiThreadRunner class that I created.

Code below in plain English : Submit 5 invocations of TestingMethodA with 10 maximum concurrent threads.

MultiThreadRunner runner = new MultiThreadRunner();           
runner.Run(new MultiThreadRunner.ParameterlessMethodDelegate(TestingMethodA), 5, 10);

 

The MultiThreadRunner class :

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);
        }
    }
}

or get the complete project from here :

 

Hope this helps with your test as well :D

Wednesday, June 25, 2008

Passing method using delegate

I was doing some code refactoring today and this is one of the things that fits nicely to remove those repetitive codes.

I have lines of code below as an example where I process some data based on certain key.

private void ProcessData()
{
    string theKey;
    Key key = new Key("A", "B");           

    theKey = key.KeyA;
    Console.WriteLine("Processing data with key : {0}", theKey);

    theKey = key.KeyB;
    Console.WriteLine("Processing data with key : {0}", theKey);

    theKey = key.KeyA + key.KeyB;
    Console.WriteLine("Processing data with key : {0}", theKey);
}

This looks simple enough, but imagine what would happen if i replace “the processing data with key…” line with 20 real codes, they suddenly become 60 lines which are repetitive, doing the same thing using the key ;)

 

So this is what I came out with, create a delegate which receives Key object then create 3 new methods which have the same signature as the delegate and will have the logic to construct the key.

private delegate string AssignKeyDelegate(Key key);
private string AssignKeyA(Key key)
{
    return key.KeyA;
}
private string AssignKeyB(Key key)
{
    return key.KeyB;
}
private string AssignKeyAB(Key key)
{
    return key.KeyA + key.KeyB;
}

 

By using this, I can process the data and construct the key based on the appropriate method which is specified in the parameter using the delegate.

private void Run()
{
    ProcessData(new AssignKeyDelegate(AssignKeyA));
    ProcessData(new AssignKeyDelegate(AssignKeyB));
    ProcessData(new AssignKeyDelegate(AssignKeyAB));
}
private void ProcessData(AssignKeyDelegate del)
{
    Key key = new Key("A", "B");           
    string theKey = del(key);
    Console.WriteLine("Processing data with key : {0}", theKey);
}

 

I provided the sample code above as a basic example only, there are many solutions that may come out with this kind of code :) The purpose is only to describe another feature that we can do with delegate.

Hope this helps :)