Home
    Shop
    Advertise
    Write For Us
    Affiliate
    Newsletter
    Contact

Multithreading in ASP.NET

Introduction

Performance and responsiveness are most the important key issues in the success of your web application. Do not relay heavly on your users to be patient. They typically quickly close unresponsive or frozen applications.

 

Sometimes you need to perform a long time task, that uses intensive CPU operations. Sometimes you are acquiring a database and waiting for the results. Not to mention when  you are performing an intensive I/O operations. As a result your, application will be dead with no response until this time consuming operation completes.

A common solution to this common problem is the use of multithreading. The .NET framework provides you with a class library that allows you to overcome this problem by using multithreading and asynchronous programming techniques. In multithreading technique, you can use the thread pool to acquire a new thread, or you can create it manually. This all depends on the level of control you want to have over the new thread.

In this tutorial we will talk about the multithreading programming technique using the thread pool.

What Is Multithreading?

Multithreading is a technique that can be used to perform time consuming tasks in a separate additional thread other than the main application thread.

When you, for example, have a time-consuming function, you may need to call this function as a response of a button click. Now, instead of freezing all your application waiting for this function to return / to finish, you can create a new thread and assign this function to. When you do this, your application interface will not be blocked and you can use it to perform other tasks. At the same time, your time-consuming task is being carried out in the background.

You can think of it as the two threads: the main one, and the newly created one. Both are running in parallel, and this improves the performance and responsiveness of your application.

Advantages and Disadvantages of Using Multithreading

Despite improving your application's performance, and avoiding unresponsive user interface, multithreading has the following disadvantages:

  • There is a runtime overhead associated with creating and destroying threads. When your application creates and destroys threads frequently, this overhead affects the overall application performance.
  • Having too many threads running at the same time decreases the performance of your entire system. This is because your system is attempting to give each thread a time slot to operate inside.
  • You should design your application well when you are going to use multithreading, or otherwise your application will be difficult to maintain and extend.
  • You should be careful when you implement a multithreading application, because threading bugs are difficult to debug and resolve.

Notes:

  • Each time a thread is created, a certain amount of memory is consumed to hold this thread context information. Hence, the number of threads that can be created is limited by the amount of available memory.

  • More threads does not mean a faster responsive application, instead it can decrease the performance of your application.

The Thread Pool

Instead of creating a thread each time we need one, and then destroying it after finishing, the .NET framework introduces the concept of thread pool. In the thread pool technique, and instead of creating a new thread whenever you need one, your application will obtain a thread from the thread pool. After that obtained thread completes its task, it will be returned to the thread pool instead of destroying it - waiting for the next acquiring. This reusability increases the overall application performance, and reduces the cost of excessive thread creation and termination.

To make use of this technique, you need to use the System.Threading.ThreadPool class. The thread pool will be created the first time you use it. The number of total threads in this pool is restricted by default to 25 threads. This means that all of these 25 threads may be busy at some point. If you need to acquire a new thread at this point, your task will be scheduled waiting for a thread to finish its task and return to the pool.

How To Use The Thread Pool

To download the complete example, click here.

To demonstrate how to use the thread pool technique in creating a multithreaded application, let us create a new web application. We will then walk through it step by step.

Open Visual Studio 2005, and create new web application with the following controls located on the "default.aspx" web form as shown in the following figure.


Figure 1 - Our web application in its design view
 

Position into the button click handler by double clicking it.

In the "default.aspx.vb" file, import the "system.Threading" name space as shown in the following line of code.

 

    1
 Imports System.Threading
 

Create a time consuming method that will be executed in background in a separate thread. To be able to assign this method to the thread pool, it must have the same signature as the "WaitCallBack" delegate. This delegate has the following declaration:

 

    Public Delegate Sub WaitCallback(ByVal state As Object)
 

This delegate represents a callback method to be executed by a thread pool thread. The "state" parameter represents the information that will be used by your time consuming method if you need to pass information to it.

So, our time consuming method will be as indicated in the following code snippet:

 

   17
     Private Sub LongTimeTask(ByVal s As Object)
   18 
   19         Dim i As Integer
   20         Dim str As String
   21         str = s.ToString
   22 
   23         For i = 0 To 1000
   24             str = str + "--" + str
   25         Next
   26 
   27     End Sub
 

Now, in the button click handler type the following lines of code:

 

    5
     Protected Sub Button1_Click(ByVal sender As _
    6     Object, ByVal e As System.EventArgs) Handles Button1.Click
    7 
    8         If ThreadPool.QueueUserWorkItem( _
    9           New WaitCallback(AddressOf LongTimeTask), TextBox1.Text) _
   10           Then
   11             Label2.Text = "Queued successfully"
   12         Else
   13             Label2.Text = "Failed"
   14         End If
   15 
   16     End Sub
 

In the line #8 of the above code, we used the ThreadPool.QueueUserWorkItem function to queue our time consuming method for execution in a separate thread from the thread pool. The first parameter to this function is a new instance of the WaitCallBack delegate that represents the method to be executed. In our case, the method to be executed is the 'LongTimeTask' method. The second parameter is the parameter to be passed to the 'LongTimeTask' method itself. In our case this parameter is the text entered by the end user in the text box control. This function returns 'True' when the queuing operation succeed, or 'False' when it fails.

Now, run your application and enter any text into the text box, then click the button, and observe the results.

It will be much better to enter long text in the text box, or to increase the number of loop iterations to get better feeling of this operation. You can also add a new text box control to the "default.aspx" page, so you can test your user interface responsiveness while you run the time consuming task at background.

That's it ...

As you can see it is so easy to use this technique to solve your annoying time consuming tasks problem. Be warned then! This ease will cost you. Read on for more!

Benefits of Using the Thread Pool

Using the thread pool is the easiest technique you can use to create a multithreaded application for the following reasons:

  • You do not have to create, manage, schedule, and terminate your thread, the thread pool class do all of this for you.

  • There is no worries about creating too many threads and hence affecting system performance. Thread pool size is constrained by the .NET runtime. The number of threads you can use at the same time is limited.

  • You need to write less code, because the .NET framework manages your thread internally with a set of well tested, and bug free routines.

Limitations of Using the Thread Pool

Despite the ease of use, the thread pool has the following limitations or disadvantages when compared to manually managing your threads:

  • With thread pool, you have no control over the state and priority of the thread.
  • With thread pool, you can not give a stable identity to your thread and keep tracking it.
  • When submitting a process to the thread pool, you have no idea when the process will be executed. Your process may be delayed when there are high demand on the thread pool.
  • The thread pool is not suitable when you want to run two tasks or processes using two threads, and need these two tasks to be processed simultaneously in a deterministic fashion.
  • The .NET framework uses the thread pool for asynchronous operations, and this places additional demand on the limited number of available threads.
  • Despite of robust application isolation, there are situations where your application code can be affected by another application code.

In situations where you can not use the thread pool because of its limitations, you can create new threads manually and manage them yourself. This technique is much more complex than using the thread pool, but it gives you more control over your threads. This will be the subject of our next tutorial, Manual Threading in ASP.NET.


Tutorial toolbar:  Tell A Friend  |  Add to favorites  |  Feedback  |