Ensure Threads Have Finished Before Method Continues

**Update – Please see here for a better way of doing this.  It’s a better solution that came around after writing this post.

This post is part extension off of my Multithreading with Parameters.  I came into a spot where I am building a monitoring page that on page load, spins off about 20-30, and then displays the outcome of those threads.  However, if you spin off a bunch of threads and don’t do anything else, the page load method finishes and you’re left with little to no content on the page because it finished before your threads.  So I implemented a thread counter.  It was a simple solution and makes the method wait until all threads have completed before it can move on.
We need a few things; a counter object, a lock object, an increment method, and a decrement method.  These are pretty straight forward and are as follows.


protected static int threadCounter = 0;
protected static object lockObject = new object();

protected void IncrememntCounter()
{
    lock (lockObject)
    {
        threadCounter++; //Increment Thread Count By 1
    }
}

protected void DecrementCounter()
{
    lock (lockObject)
    {
        threadCounter--; //Decrement Thread Count By 1
    }
}

Now let’s look how this gets applied.  [more]In our method where we spin off the threads, we simply call the increment method.


//Create new thread
Thread logThread = new Thread(LogServiceCall); 
//Start new threadlog
Thread.Start(logParams);
//Increment our thread 
counterIncrementCounter();

As I am sure you have figured out, the method that gets spun off in the thread, we need to call the decrement counter upon completion of that method.


private void LogServiceCall(object parameterObject)
{
    LogginParams pLoggingParams = (LogginParams)parameterObject;
    lock (lockObject)
    {
        LogServiceCall(pLoggingParams.Log, pLoggingParams.Info, pLoggingParams.Number);
    }

    DecrementCounter();
}

Now we have our counter set up.  When we spin off a new thread we are adding one to the counter, and then when our thread finishes we are decrementing the counter by one. Now the last piece of the puzzle is in the method that you are wanting to wait for the threads to complete, we simply check our thread counter for number remaining.


while (threadCounter > 0)
{
    Thread.Sleep(500); //Make it pause for half second so that we don’t spin the cpu out of control.
}

This was a nice way to ensure threads have finished and that the method would not continue until everything was done.  My threads were small and often times finish quickly.  I added asynchronous threads and chopped the page loading speed over half.  If you have another way of going about doing this please share, I would love to hear to if there are better and different ways of doing this.


Multithreading with Parameters

I ran into a task the other day to make my service calls run asynchronously for performance reasons and solved this by Multithreading with Parameters.  When the front of site gets pounded, the logging service will be making too many inline calls causing performance problems. So I had to do some minor tweaking which really was only implementing to new methods.

So basically we had a call right into our service.

_service.LogServiceCall(string log, string info, long number);

First change we make is call a new method to spin off new threads and we will need to create a new object to store the parameters in.

_service.LogServiceCallInParallel(string log, string info, long number); //New Method Call

public class LogginParams
{
    public string Log { get; set; }
    public string Info { get; set; }
    public long Number { get; set; }
}

When creating a thread with parameters you have to pass in an object with parameters. So we will create LoggingParams object, start the thread, then split the parameters back out.  Let’s take a look at the thread starting.

public void LogServiceCallInParallel (string log, string info, long number)
{
    //Create object
    LogginParams logParams = new LogginParams
    {
        Log = log,
        Info = info,
        Number = number
    };

    //Create new thread.
    Thread logThread = new Thread(LogServiceCall);

    //Start new thread
    logThread.Start(logParams);
}

Now all we have to do is call an overloaded method of our original method so that it will work as designed just now with multithreading.

private void LogServiceCall(object parameterObject)
{
    LogginParams pLoggingParams = (LogginParams)parameterObject;
    LogServiceCall(pLoggingParams.Log, pLoggingParams.Info, pLoggingParams.Number);
}

So as you can see here, all we are doing is breaking back out the object and then calling our original method that was being used.


StackOverflow Profile