Recycling an Application Pool with C# (Part 2)

28. July 2011 12:24 by Matt Wrock in   //  Tags:   //   Comments (6)
DotNetShoutout
DotnetKicks

The other day I shared how to use the DirectoryServices namespace to restart an app pool via C# code. The code I used had two key flaws:

  1. It used a Thread.Sleep(2000) to wait for the old app pool to be destroyed.
  2. The use of DirectoryServices required the enabling of the windows feature: IIS Metabase and IIS 6 configuration compatibility.

Also just to recap why you would even want to do this: My use of this code is for writing integration tests of web app functionality. It allows me to test scenarios where I want to ensure a certain outcome after the application restarts. It also helps to isolate test state from one test to another.

Anyhoo, a coworker of mine, @mmanela (Matt Manela) mentioned hosting a powershell script instead of the DirectoryServices implementation. As we discussed it further, we assumed that the PowerShell WebAdministrationiModule was probably using some other API and that it would be interesting to discover what that was and see if you could use that. Well after spending some quality time with reflector and the WebAdministrationModule DLLs, I was not able to tell what that API was. However, I did discover another API that appeared to be a better alternative to DirectoryServices.

The API can be found in %WinDir%\system32\Inetsrv\Microsoft.Web.Administration.dll. See this post for a good overview. Here is my new helper method:

public static void RecyclePool()
{
using (var manager = new ServerManager())
{
var pool = manager.ApplicationPools["RequestReduce"];
Process process = null;
if(pool.WorkerProcesses.Count > 0)
process = Process.GetProcessById(pool.WorkerProcesses[0].ProcessId);
pool.Recycle();
if(process != null)
{
while (!process.HasExited)
Thread.Sleep(0);
process.Dispose();
}
}
}

So in addition to using a different API, I’m also no longer using the hacky Thread.Sleep(2000) to wait for the app pool to die. Instead, I use this API to get the Process ID of the about to be recycled app pool. I then wait for the pool to exit. I have tested this and it works perfectly. So now my tests move on as soon as the app pool is completely destroyed. I don’t have to wait any extra time in case this happens more quickly than two seconds and I don’t risk a failed test if two seconds is not long enough. In case you are wondering why it is so important to wait for the old app pool’s worker process to terminate before proceeding, it is because I may have cleanup code that deletes files and that code will likely fail if the old worker process had a lock on the file.

Comments (6) -

Victor
Victor
11/30/2011 1:33:50 AM #

Nice detective work!  I've been struggling with this for a couple of days now.  I have to ask though, what's the significance of

Thread.Sleep(0);

Is there a reason for not just using empty braces? Or is it just a matter of style preference?

Matt Wrock
Matt Wrock
11/30/2011 4:03:13 PM #

Hi Victor,

The reason I use Thread.Sleep(0), is that it will allow other processes on the machine to do work while I wait for the app pool to recycle. The danger of not doing this is that I can potentially pin CPU as I hog it while I wait. The risk here is higher, the fewer cores on the machine.

Try running this code and watch cpu in task manager:

   var watch = new Stopwatch();
   watch.Start();
   while(watch.ElapsedMilliseconds < 30000){}

You should see ono of your cores max out on cpu for 30 seconds.

Passionate Developer
Passionate Developer
1/6/2012 6:59:36 PM #

Great article.  What namespace is ServerManager under.  I just get a squigly line in my code under "new ServerManager()" and can't seem to find the correct namespace for c# or add the right reference.  I am running .net 3.5 and running it under IIS 7 on Windows Server 2008 R2.

Matt Wrock
Matt Wrock
1/7/2012 12:27:16 PM #

Passionate Developer: The namespace is Microsoft.Web.Administration

ei theint
ei theint
6/11/2012 10:35:54 AM #

I cannot see Web.Administration under Microsoft.

Thank you.

mwrock
mwrock
6/12/2012 3:28:52 PM #

@ei: You may need to explicitly reference %WinDir%\System32\InetSrv\Microsoft.Web.Administration.dll

Add comment

biuquote
  • Comment
  • Preview
Loading

About Me

Hey thats me!

I'm Matt Wrock with over thirteen years of experience architecting scalable, distributed, high traffic web applications. I currently live in Woodinville, WA with my wife, two daughters, three dogs and cat. I work for Microsoft as a Sr. Software Engineer working in Cloud Developer Services. I'm also project founder and owner of http://www.requestreduce.org and a committer to http://chocolatey.org.

Month List