.NET and Agile Software Design RSS 2.0
# Wednesday, August 20, 2008

I'm glad to confirm that the ThreadPool bug introduced in .NET 3.5 has been fixed in SP1 for .NET 3.5.

For more background information, look at these posts.

  1. .NET 3.5 Brings Breaking Changes to ThreadPool
  2. Breaking Changes in the ThreadPool: The Movie
  3. Follow up on .NET 2.0 SP1 ThreadPool Bug
  4. More on the ThreadPool Bug in .NET 2.0 SP1

Now go forth, and create some threads!


Wednesday, August 20, 2008 11:18:02 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0] -
DevelopMentor | Visual Studio
# Wednesday, July 02, 2008
When I talk about LINQ people often ask whether it’s possible to have dynamic queries with LINQ. An example of this is presenting the user with a UI that allows them to optionally filter by some criteria or other and sort by some criteria. This was straightforward if you built-up a SQL string in code.

The compiled, static nature of LINQ makes dynamic queries appear difficult at first. They are not and this video and sample application shows you how to accomplish just this.


                        Screen shot of sample application

You can download the source code here:

           Kennedy-Dynamic-Linq.zip (88.34 KB)

And you can watch the screencast video here:

          Kennedy-Dynamic-Linq.wmv (35.7 MB)

Of course, if you like this post, please kick it: kick it on DotNetKicks.com


Wednesday, July 02, 2008 1:08:00 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0] -
DevelopMentor | Talks | Visual Studio
# Monday, March 24, 2008
If you'v been using my Visual Studio Recent Files Utility, then you may be interested to find out that I just released it as open source on CodePlex here.

    Visual Studio Recent Files Utility on CodePlex

Enjoy!

Monday, March 24, 2008 6:06:27 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0] -
Open Source | Tools | Visual Studio
# Monday, March 03, 2008
Here's a followup post on the .NET ThreadPool bug that I described here:

Breaking Changes in the ThreadPool: The Movie

I have been in touch with the guys who are in charge of the ThreadPool and they have both confirmed that this is a bug and that they are planning on fixing it in .NET 2.0 SP2 - but they are not sure of the timeline for its release.

In the meantime, Vance Morrison, a .NET Runtime Performance Architect at Microsoft, has given me this work-around.

Take this "broken" code:

	private static void UseThreadPool(int count)
        {
            for ( int i = 0; i < count; i++ )
            {
                ThreadPool.QueueUserWorkItem(
                    delegate { SlowMethod(); } );
            }
        }
And add a strategic Thread.Sleep and it's fixed:

	private static void UseThreadPool(int count)
        {
            for ( int i = 0; i < count; i++ )
            {
                ThreadPool.QueueUserWorkItem(
                    delegate { SlowMethod(); } );
Thread.Sleep(1);
            }
        }



Monday, March 03, 2008 2:49:40 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0] -
DevelopMentor | Visual Studio
# Tuesday, February 26, 2008
Well, my recent post on .NET 3.5 Brings BREAKING Changes to ThreadPool sparked quite a bit of interest in the .NET community.

But this is also something difficult to convince people of because it depends so heavily on configuration. The source code doesn't change, the environment does.

So I've put together a screencast demonstrating the problem and elaborating further. If you doubt the validity of the previous post, or can't reproduce the problem, please watch the video:




                     Download the video (approx 18 MB)

Kick it: kick it on DotNetKicks.com

In the video I work with a modified version of the program. Here's that for your enjoyment:

The application: NetThreading.exe (From Video).zip (2.59 KB)

The source code:
using System;
using System.Threading;

namespace NewThreadPoolBehavior
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            Console.WriteLine( "Running on " + Environment.Version );
            int w, c;
            ThreadPool.GetMaxThreads( out w, out c );
            Console.WriteLine( "Max Currently: " + w + ", " + c );
            ThreadPool.GetMinThreads( out w, out c );
            Console.WriteLine( "Min Currently: " + w + ", " + c );

            Console.WriteLine( "Set min thread count 20? (y/n) " );
            string txt = Console.ReadLine();
            if ( txt == "y" )
            {
                Console.WriteLine( "Setting min to 20" );
                ThreadPool.SetMinThreads( 20, 100 );
                ThreadPool.GetMinThreads( out w, out c );
                Console.WriteLine( "Min Currently: " + w + ", " + c );
            }
            UseThreadPool( 200 );

            Console.ReadLine();
        }

        private static DateTime startTime;

        private static void UseThreadPool(int count)
        {
            startTime = DateTime.Now;
            for ( int i = 0; i < count; i++ )
            {
                ThreadPool.QueueUserWorkItem(
                    delegate { SlowMethod(); } );
            }
        }

        private static int concurrent = 0;

        private static void SlowMethod()
        {
            TimeSpan dt = DateTime.Now - startTime;
            concurrent++;
            Console.WriteLine( "Starting ops (" + concurrent + " concurrent, elapsed=" +
dt.TotalSeconds.ToString( "N3" ) + " sec.) " );
            Thread.Sleep( 20000 );
            Console.WriteLine( "Finished ops (" + concurrent + " concurrent)" );
            concurrent--;
        }
    }
}

Tuesday, February 26, 2008 1:21:04 PM (Eastern Standard Time, UTC-05:00)  #    Comments [2] -
DevelopMentor | Visual Studio
# Monday, February 25, 2008
Holy smokes! I thought we had figured out something significant when I posted .NET 3.5 Brings Major (Undocumented) Changes to ThreadPool where we discovered that the .NET 3.5 ThreadPool changed the allocation algorithm for adding threads from linear to logarithmic.

This is bigger. [Recently updated see note below]

Here's the scenario. I have a server - say in the financial sector - that must process many requests and it must get up to speed immediately. I can't pay the 500 ms warm up time for the ThreadPool (.NET 2.0) or the even slower model in .NET 2.0 SP1. What do I do? I call ThreadPool.SetMinThreads(x, x) where x < (the current max), but much higher than 2 (the default). So I might call ThreadPool.SetMinThreads(100, 100) or something like that.

In .NET 1.0 - .NET 2.0 (without SP1) you would go from the warm up time model:


                 warm up time model (.NET 2.0)

To this immediate "ready" threading model.


                 ready model (.NET 2.0)

Notice that we immediately have 100 threads available in this case. BUT, and here's the but: .NET 3.5 (read .NET 2.0 SP1) *ignores* SetMinThreads. Oh, it claims to respect SetMinThreads:

   Running on 2.0.50727.1433
   Max Currently: 500, 1000
   Min Currently: 2, 2
   Set min thread count 100 (y/n)? y
   Setting min to 100
   Min Currently: 100, 100

But, look at the thread graph that results!


           ready model (.NET 2.0 SP1  -- i.e. .NET 3.5)

I don't know about you, but that doesn't look any different AT ALL than if we do not call SetMinThreads:


         warm up time model (.NET 2.0 SP1  -- i.e. .NET 3.5)

What do we conclude from this? .NET 2.0 SP1 does not respect ThreadPool.SetMinThreads. To me, that's a big breaking change. My financial app just stopped working. Yikes! So what happened to my thread pool and SetMinThreads in .NET 2.0 SP1? Anyone?

Kick it: kick it on DotNetKicks.com

Don't take my word for it. Run this program on both .NET 2.0 (SP0) and .NET 2.0 SP1 and you'll see for yourself.

Here's the EXE:

   NetThreading.zip (2.3 KB)

And the source code is below:
using System;
using System.Threading;

namespace NewThreadPoolBehavior
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            Console.WriteLine( "Running on " + Environment.Version );
            int w, c;
            ThreadPool.GetMaxThreads( out w, out c );
            Console.WriteLine( "Max Currently: " + w + ", " + c );
            ThreadPool.GetMinThreads( out w, out c );
            Console.WriteLine( "Min Currently: " + w + ", " + c );

            Console.WriteLine( "Set min thread count 100? (y/n) " );
            string txt = Console.ReadLine();
            if ( txt == "y" )
            {
                Console.WriteLine( "Setting min to 100" );
                ThreadPool.SetMinThreads( 100, 100 );
                ThreadPool.GetMinThreads( out w, out c );
                Console.WriteLine( "Min Currently: " + w + ", " + c );
            }
            UseThreadPool( 200 );

            Console.ReadLine();
        }

        private static void UseThreadPool(int count)
        {
            for ( int i = 0; i < count; i++ )
            {
                ThreadPool.QueueUserWorkItem(
                    delegate { SlowMethod(); } );
            }
        }

        private static int concurrent = 0;

        private static void SlowMethod()
        {
            concurrent++;
            Console.WriteLine( "Starting ops (" + concurrent + " concurrent)" );
            Thread.Sleep( 20000 );
            Console.WriteLine( "Finished ops (" + concurrent + " concurrent)" );
            concurrent--;
        }
    }
}
[Update: 2/25/2008 - You may be thinking so what's the big deal? Most applications don't directly program against the ThreadPool so this is just some edge case. To make this more real for everyone, this applies to you if you use any of the following: ASP.NET, WCF, .NET Remoting, Delegate.BeginInvoke, SqlCommand.BeginExecute*, Windows Workflow, and more. Sounds serious now right?]

[Update: 5/12/2008 - Please see my lastest followup on this topic: More on the ThreadPool Bug in .NET 2.0 SP1.]


Monday, February 25, 2008 6:47:28 PM (Eastern Standard Time, UTC-05:00)  #    Comments [4] -
DevelopMentor | Visual Studio
# Thursday, February 07, 2008

It was all going so smoothly. Jason Whittington, Mark Smith and I were teaching the big DevelopMentor event here in Los Angeles (Guerrilla.NET) when my presentation on the ThreadPool took a nose dive. It started with a great joke involving Wilson (the volleyball from Cast Away).

Wilson and I built an application to compute a multiplication table where each computation was (artificially) slow. To speed it up we threw it at the thread pool using delegate.BeginInvoke. We figured that the ThreadPool would allocate 25 or so threads and the table would display quickly. Here's the expected output - pretty much the same thing we've seen since about .NET 1.0:

    

Each color represents the thread that did that computation.

For the last 7 years, the behavior has been that as the ThreadPool was overloaded, it would steadily start up new threads at the rate of one every 500 milliseconds until it hits its upper limit (typically). Using Performance Monitor (perfmon) we can watch the thread pool adding threads. It usually looks something like this:

    

Much to our surprise we saw completely different behavior. The thread pool added the first 15 or so threads quickly (as expected) but then stalled. New threads were not created every 500ms, instead they were added at increasingly long intervals. My demo took almost twice as long to run as it had the last time I did this demo a few months ago.

Jason, Mark, and I took this code, ported it back to .NET 1.1 and ran it side-by-side with .NET 3.5 and here's what we saw (blue = 3.5, red = 1.1):

    

As of .NET 3.5 the upper limit of the ThreadPool was increased: Knew that.

But, it appears that v3.5 of the CLR changes the policy for adding threads to the thread pool. Rather than adding threads regularly when under load the thread pool uses a logarithmic backoff. My colleague Jason Whittington remarked that this behavior looked similar to the behavior of the thread pool in "Rotor" (the shared-source version of the CLR). We speculated that this backoff algorithm makes sense given the new 250-thread per CPU maximum - it would take a long time to reach that if the runtime waits longer and longer to start a new thread. The 250-thread limits makes it less likely that your application will deadlock the thread pool, and the exponential backoff algorithm keeps the thread pool from creating too many threads too quickly.

Why should you care? Usually you won't, but it could have dramatic impact if you count on that behavior. For example, in our contrived case, .NET 1.1 ran about twice as fast as .NET 3.5 ( ! ):

    

Here's the program and source code (trimmed down to run in both .NET 1.1 and 3.5).

    Math.zip (6.38 KB)

Needless to say, Wilson and I felt kinda stood up.

      kick it on DotNetKicks.com

Please see the follow up post on Breaking changes and now there is screencast, movie version as well.


Thursday, February 07, 2008 12:33:32 AM (Eastern Standard Time, UTC-05:00)  #    Comments [4] -
DevelopMentor | Talks | Visual Studio
# Wednesday, January 30, 2008
I recently wrote up an overview of the new ASP.NET MVC Framework for the Developments newsletter.

I encourage you to read it on the DevelopMentor website. It's an interesting programming model.


Wednesday, January 30, 2008 10:49:49 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0] -
Visual Studio
# Thursday, December 06, 2007
I've been playing with my fresh copy of Vista Ultimate - which I am surprised to find that I absolutely love.

Being a big fan of System.Transactions, I naturally wanted to use it with Vista's TxF (Transactional NTFS) file system. But unlike the data libraries, the file APIs don't auto-enlist in the transaction. In fact, there are only COM / PInvoke APIs currently.

There is a nice article about how to work with these APIs in the MSDN article: "NTFS: Enhance Your Apps With File System Transactions". But I was unimpressed with the managed wrapper they created there. In particular, I don't like that the lifetime of the file stream is not forced to be part of a client initiated transaction scope. So I built my own transactional file stream in C#. With this TxFileStream class, you can write succinct code like this:

[Test]
public void ContentAddedDoesNotPersistsAfterRollbackTest()
{
    string fileName = "file3.txt";
    string originalContents = "First contents";
   
    using (TransactionScope scope = new TransactionScope())
    {
        string newContents = "Hello transacted NTFS.";
        using (StreamWriter sw = TxFileStream.CreateWriter(fileName))
        {
            sw.Write(newContents);
        }

        using (StreamReader sr = TxFileStream.CreateReader(fileName))
        {
            string text = sr.ReadToEnd();
            Assert.That(text, Is.EqualTo(newContents));
        }
        // no call to scope.Complete() forces a rollback.
    }

    Assert.That(File.Exists(fileName));
    Assert.That(File.ReadAllText(fileName),
        Is.EqualTo(originalContents));
}


Feel free to download the code and give it a spin!

    Kennedy.TxFiles.zip (36 KB)

Of course, my library comes with comprehensive unit tests. Look here first to figure out how out use the library.

Note: I fixed a bug in creating transactional StreamWriter's in append mode. Previously they partially overwrote the existing content.

Thursday, December 06, 2007 11:51:52 PM (Eastern Standard Time, UTC-05:00)  #    Comments [2] -
Visual Studio
# Wednesday, September 12, 2007
Welcome to my third Visual Studio tricks post. This time it's more of a utility, than a tip. I want to talk about managing the recently projects list. If you're like me, then you work with many different projects (especially after I teach a class) and your recent project list becomes polluted with projects you don't care about.

     


In this post, "Recent Projects in Visual Studio 2005", .net DEvHammer discusses how to access the registry to alter that list.

Well, I didn't feel like going to the registry everytime I wanted to clean that list. So I whipped up a simple UI to manage that list (basically manage that registry list).




You're welcome to download this program if it looks useful to you. I decided to publish it via ClickOnce so it will always be up-to-date. If you're using FireFox, you'll need to FFClickOnce add-on to make this work.

    Install Visual Studio Recent Files Utility (approx 200 KB)

kick it on DotNetKicks.com

I hope you enjoy it!

This project is now hosted on CodePlex and is Open Source.
Wednesday, September 12, 2007 8:27:40 PM (Eastern Standard Time, UTC-05:00)  #    Comments [4] -
Tools | Visual Studio | Open Source
# Wednesday, August 22, 2007
Welcome to the next installment of my Visual Studio Tricks series. Continuing on from last time when I discussed how to quickly switch between startup projects using hot-keys, we'll cover another startup project trick.

Here's the scenario. Suppose you're working on a brand new WCF application that has both a client and server piece.

        

You need to start both the client and server to accomplish anything interesting. Most people fumble around starting the server, then the client.

Did you know that you can tell VS to run both at once. You just have to know where to look. The place to look is the properties of the solution. i.e. Right-click on the solution and choose properties and you'll get this dialog:


                                   Click for full image

By default this is set to "Single startup project". But you just have to select "Multiple startup projects" and you're on your way to smooth sailing with your client / server application. You even get debugging of both the client and server when you press F5.

Enjoy!
Wednesday, August 22, 2007 10:09:55 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0] -
Visual Studio
# Monday, July 30, 2007

Welcome to my Visual Studio Tricks series. Here I’ll give you some quick tips for saving you lots of time when working with Visual Studio.

In this first installment, I'll show you how to switch between projects more quickly. Any time you work on a large project, you’ll have several projects that you might want to launch from within a solution. This includes at least an EXE and a unit test project right? Hint, hint, nudge, nudge.

Typically you do this by right-clicking on the project and say “Set as Startup Project”. But did you know you can set a hot key for this? Just go to the keyboard options in VS 2005 and type “SetAsStar” and you’ll see this screen:


If you select the startup project option, you can now add a keyboard shortcut. Sounds simple but it saves lots of time and fumbling with the mouse. There are no hotkeys assigned by default. Note that I chose <ctrl>-<shift>+P. That seems like a good choice for me.


Monday, July 30, 2007 2:42:55 PM (Eastern Standard Time, UTC-05:00)  #    Comments [1] -
Visual Studio
Archive
<August 2008>
SunMonTueWedThuFriSat
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456
About the author/Disclaimer

Disclaimer
These postings are provided "AS IS" with no warranties, and confer no rights.

© Copyright 2008
Michael C. Kennedy
Sign In
Statistics
Total Posts: 29
This Year: 14
This Month: 1
This Week: 1
Comments: 28
Themes
Pick a theme:
All Content © 2008, Michael C. Kennedy
DasBlog theme 'Business' created by Christoph De Baene (delarou)