Click here to Skip to main content
15,885,141 members
Articles / Web Development / ASP.NET

ASP.NET Multithreading in a Web Farm Environment

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
2 Aug 2009CPOL3 min read 13.3K   7  
ASP.NET Multithreading in a web farm environment

In one of my recent projects, I have a situation where I need to generate two files on the server based on user input. Both files can be quite big (in terms of mobile devices), and take a long time to generate by the server and to download by the user. The two files must be generated sequentially, as the second file depends on the first. One way to implement this would be to generate both files and then return to the user the download URLs in one request-response. The problem with this approach is that the user has to wait for a very long time before the server finishes the job. An obvious improvement is to return immediately after the first file is generated, and at the same time to spawn a new thread to generate the second file. This way, upon the request responded, the user can start to download the first file while the server is working on the generation of the second file. One problem with this approach is that the user will not know when the second file is ready for download. My solution is to create another page that allows the user to check the status of the second file. If it is ready, the response will include the download URL so the user can start to download it. If it is not ready, the user can either wait or do something else and check the status later. This works fine in my case, as the downloading time for the first file is almost always longer than the time needed to generate the second file.

Another problem with this approach is that my ASP.NET application is running in a web farm environment in which I have a shared file store for the generated files and the newly spawned thread does not have proper permissions to write to the shared file store. The following diagram shows my simple web farm of two web servers, WS1 and WS2, and the file store. The file store is just a shared folder on one of the two web servers.

I use the steps below to configure the web servers so they can access to the shared folder. These steps apply to Windows 2000 (Advanced) Server OS. Yes! I'm still using Windows 2000 servers. :)

  1. Create a Windows user account, say "SharedUsr", on both WS1 and WS2.
  2. Add <identity impersonate="true" userName="SharedUsr" password="xxxxxx"/> to web.config on both servers.
  3. Run these commands on both servers to grant "SharedUsr" access to the shared folder used by my ASP.NET application:
    C:\WINNT\Microsoft.NET\Framework\v2.0.50727>aspnet_regiis -ga WS1\SharedUsr
    C:\WINNT\Microsoft.NET\Framework\v2.0.50727>aspnet_regiis -ga WS2\SharedUsr
  4. Make sure "SharedUsr" has write permission on the shared folder

This, however, does not work if the current thread spawns a new thread to write to the shared folder, because the new thread does not automatically impersonate "SharedUsr". I have to write code to force the impersonation. The following is the code. I have left out some details for clarity.

C#
......
using System.IO;
using System.Security.Principal;
using System.Threading;

public partial class GenerateFiles : System.Web.UI.Page
{
    private WindowsIdentity wid = null; 
    protected void Page_Load(object sender, EventArgs e)
    { 
        //Generate file1 ......

        wid = WindowsIdentity.GetCurrent(); //This is "SharedUsr" 
        try
        {
            //Use a thread from the threadpool to generate file2
            if (ThreadPool.QueueUserWorkItem(new WaitCallback(File2Callback),
                new File2Generator(file2Location)))
            {
                //Return file1 URL to user so he can start to download file1
                Response.Write(file1URL); 
            }
            else
            {
                Response.Write("Server too busy. The work item could not be queued.");
            }
        }
        catch (Exception ex)
        {
            Response.Write(ex.Message);
        }  
    }

    private void File2Callback(object o)
    {
        //Set the pooled worker thread's principal to that of wid   
        WindowsPrincipal principal = new WindowsPrincipal(wid);
        Thread.CurrentPrincipal = principal;

        //Make the pooled worker thread to impersonate 'SharedUsr'
        WindowsImpersonationContext wic = wid.Impersonate();

        //Generate file2
        File2Generator f2gen = (File2Generator)o;
        f2gen.Generate();

        //Undo impersonation before return to threadpool
        wic.Undo();
    }
}

In the beginning of Page_Load, we assume file1 has been generated. Then, we use a worker thread from the threadpool to queue the generation of file2 for execution. The QueueUserWorkItem method has two parameters. The first parameter specifies the function to be called when the worker thread has its turn. The second parameter is the data to be passed to the function. In our case, it's an instance of File2Generator class, which encompasses necessary data and functionality to generate file2. The implementation of File2Generator is not listed here because the detail is not important for making the point.

The callback function, File2Callback, will be executed on the worker thread that has the Windows identity "ASPNET", not "SharedUsr". So in it, we need to change the worker thread's impersonation before calling the Generate method of File2Generator.

License

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


Written By
Software Developer (Senior) Pharos
United States United States
I work as a Principal Software Engineer for Pharos. I develop location-based services and applications using Microsoft .Net Technologies. I am a Microsoft Certified Application Developer (MCAD) and Microsoft Certified Solution Developer (MCSD). I have more than 20 years of experience in computer programming and software development. I'm currently interested in topics related to C#, APS.Net, SQL Server, Windows Programming, Web Programming, AJAX, Bing Maps, Google Maps, and e-Commerce.
My blog site: http://www.tofuculture.com

Comments and Discussions

 
-- There are no messages in this forum --