Click here to Skip to main content
Click here to Skip to main content

Simple mutlithreaded application

, 6 Apr 2009
Rate this:
Please Sign up or sign in to vote.
A simple mutlithreaded application using ThreadPool.

Introduction

During some performance testing phases, you often discover that there is a lack in the software performance, and that the solution is not responding, or is not completing its tasks in an acceptable time. This can be caused due to many issues, some related to the code efficiency, or external dependencies, or the execution flow.

In this article, we will see an approach that can help in resolving performance issues. Multi-threading can be a good solution. Multithreading is a popular programming and execution model that allows multiple threads to exist within the context of a single process. These threads share the process' resources but are able to execute independently. The threaded programming model provides developers with a useful abstraction of concurrent execution. However, perhaps the most interesting application of the technology is when it is applied to a single process to enable parallel execution on a multiprocessor system.

Background

You should be familiar with Microsoft .NET, and multi-threading implementation in C#.

Using the code

In this example, we will look at a simple multi-threaded application. We will use the ThreadPool class and the class will be responsible for creating threads, and queuing requests to be picked up later by the created threads. Alternatively, you can do your own thread creation, assignment, and disposing.

First, we will start by creating a parent thread, and assign the delegate to be called. The Start function is a void function with no parameters that will be called once the main thread is created.

Thread parent = new Thread(new ThreadStart(Start));
parent.Start();

The Start function is responsible for creating the threads and queuing the items in the ThreadPool.

private void Start()
{
    // maximum threads cannot be less than the number of CPUs
    ThreadPool.SetMaxThreads(int.Parse(txtMaxThreads.Text), int.Parse(txtMaxIOThreads.Text));
    ThreadPool.SetMinThreads(int.Parse(txtMinThreads.Text), int.Parse(txtMinIOThreads.Text));

    int requestCount = Convert.ToInt32(txtNumberOfRequest.Text);
    AutoResetEvent[] _waitAllEvents; // Array of objects to wait upon.

    // Create an array of objects to wait upon; we need one per thread
    _waitAllEvents = new AutoResetEvent[requestCount];
    // Populate array of waiting objects, one for each work item
    for (int i = 0; i < requestCount; i++)
    {
        _waitAllEvents[i] = new AutoResetEvent(false);
    }
    for (int rqCounter = 0; rqCounter < requestCount; rqCounter++)
    {
        WaitCallback callBack = new WaitCallback(InternalCommand);
        ThreadPool.QueueUserWorkItem(callBack, 
          new Pair(rqCounter.ToString(), _waitAllEvents[rqCounter]));
    }

    // Wait until all our threads have signaled their wait object is done.
    if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
    {
        // WaitAll for multiple handles on an STA thread is not supported.
        // ...so wait on each handle individually.
        foreach (WaitHandle myWaitHandle in _waitAllEvents)
            WaitHandle.WaitAny(new WaitHandle[] { myWaitHandle });
        System.Diagnostics.EventLog.WriteEntry("Finished Execution " + 
                           "STA Mode - Logs are : \n\n", result);
    }
    else
    {
        WaitHandle.WaitAll(_waitAllEvents);
        MessageBox.Show("Finished Execution MTA Mode - Logs are : \n\n" + result);
    }
}

InternalCommand is where the real execution happens, where you can add, delete, or do anything. After you finish, you have to inform the ThreadPool that you finished execution. And, that is done by setting the AutoResetEvent.

private void InternalCommand(object state)
{
    string threadID = (string)((Pair)state).First;
    lock (result)
    {
        result += "Thread with the thread id ";
        result += threadID;
        result += " was called";
        result += "\n";
    }
    AutoResetEvent autoResetEvent = ((Pair)state).Second as AutoResetEvent;
    // Set our wait item to indicate we are done here.
    autoResetEvent.Set();
}

Example execution flow

This example execution flow can be described as follows:

  1. The ThreadPool will be initialized based on the user input.
  2. Based on the request count, the request event handlers will be created.
  3. All request will be queued into the ThreadPool queue, where the ThreadPool will create working threads to handle the requests.
  4. At the execution function, whenever it finishes execution, the handler will be set.
  5. When all event handlers are set, a message box will be shown.

History

  • Version 1.0.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Wael Al Wirr
Program Manager INVESTBANK
Jordan Jordan
Wael Al Wirr’s Specialties:
•Microsoft BizTalk Server 2004, 2006, 2010
•ASP.Net, C#, ADO.Net and .Net Framework (1.1, 2.0, 3.0, 3.5, 4.0)
•Windows Communication Foundation
•Windows Workflow Foundation
•Windows AppFabric
•ADO.NET Entity Framework
•Microsoft Line Of Business Adapter Framework
•SQL Server 2000, 2005
•Web development
•HTML, XML, XSD, XSLT
•JavaScript
•Database design
•Web Services
•Build, deployment script
•Microsoft Source Safe, Microsoft Team Foundation Server
Follow on   Twitter

Comments and Discussions

 
Generalok article PinmemberDonsw11-May-09 8:09 
GeneralRe: ok article PinmemberWael Al Wirr11-May-09 19:53 
Generallock(result) Pinmemberleeloo9996-Apr-09 21:47 
GeneralRe: lock(result) PinmemberWael Al Wirr6-Apr-09 22:43 
AnswerRe: lock(result) PinmemberThaiCoon6-Apr-09 22:57 
GeneralRe: lock(result) PinmemberWael Al Wirr6-Apr-09 23:28 
GeneralRe: lock(result) PinmemberThaiCoon7-Apr-09 0:25 
GeneralRe: lock(result) PinmemberWael Al Wirr7-Apr-09 0:34 
GeneralRe: lock(result) PinmemberThaiCoon7-Apr-09 3:10 
GeneralRe: lock(result) PinmemberWael Al Wirr7-Apr-09 3:31 
GeneralRe: lock(result) PinmemberThaiCoon7-Apr-09 3:55 
GeneralRe: lock(result) PinmemberWael Al Wirr7-Apr-09 4:05 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140827.1 | Last Updated 6 Apr 2009
Article Copyright 2009 by Wael Al Wirr
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid