Wednesday, August 25, 2004

Sheesh another nerd post.  I thought this might be useful information for the community.

If you're using multiple threads in the execution of an ASP.net page, don't count on Response.End() to do what you think it might do.  Looking back it's pretty intuitive, I just didn't think about it.

At work, we have some pages that can take several minutes to execute.  They can pull millions of rows from the database and process them and do all kinds of craziness.  As a result, users don't like to sit around and watch Internet Explorer's progress bar decieve them time and again.  I implemented a progress mechanism to let the user know what is happening.  I went through several iterations before I come up with something really easy to work with.  It's completely transparent to the developer, and allows them to “push” progress messages onto a stack (using the wonderful “using“ statement), which is rendered for the user at an interval during the lifetime of a page.  It preserves the behavior of postbacks and Server.Transfers, but does break redirects if they happen after the progress gets started (which I hardly ever do).

Anyway, the point of the story is to tell you about Response.End.  The progress updating happens on a worker thread from the ThreadPool.  When I implemented it, I thought it would be nice to detect if a user has closed the browser or hit stop.  Then we could save some resources if no one is listening anymore.  So, before updating the progress, I do a Response.IsClientConnected, and if they aren't, I was calling Response.End().  This seemed to work at first, because it does do something, the problem is it doesn't stop what's going on in the main thread.

Reflector (the most useful CLR tool ever) reveals that Response.End() is basically just calling Thread.CurrentThread.Abort(), along with doing some clean-up and such.  Notice the CurrentThread...oops.  All I was doing was ending my progress rendering thread.  Like I said, it makes perfect sense now.

So, what do you do about it?  Well, I'll come up with something.  It shouldn't be too hard, but it will be pretty specific to my situation, so there's no real universal answer, unless Microsoft were to change the implementation so that it was keeping track of the threads and killing the main one, although then my worker threads wouldn't die.  Chances are if you've implemented some kind of multi-threading in your ASP.net pages, you can figure it out.

posted on Wednesday, August 25, 2004 2:06:47 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]

I'll forever chuckle when I read that title.  Maybe you will too after you read this.

I was aware of the Nullable generic struct in the 2.0 CLR, but I only just now figured out that they've built direct support for it into C# 2.0.  This is awesome!  At work, we currently have a whole bunch of structs that add null support to the value types in the CLR.  So we have NullableSingle, NullableDouble, NullableUInt64, etc.  This helps us incredibly to match the database concept of numbers and such that can have null values.

I've been looking forward to Nullable for some time, but now I'm absolutely ecstatic about the C# support for it.  Using the magic question mark, I can declare a value type to be nullable.  For instance:

bool? hasHairOnHead = false;

Now you get the title joke, right? This means that hasHairOnHead can be set to null, not just through Nullable's HasValue method, but by actually setting it to null:

hasHairOnHead = null;

Freaking awesome, eh?  So now, the Headless Horseman's hasHairOnHead value can more accurately express his status. (OK, it was the first example I thought of).  The same goes for null comparisons and such!

Of course now I'll get confused reading documentation...Is that a question or a nullable type?  Just try to decipher this faq: Why don't nullable relational operators return bool? instead of bool?

That little question mark is going to save me alot of headaches.  Now I just have to wait for it to be out of beta. 

posted on Wednesday, August 25, 2004 9:16:14 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Monday, August 23, 2004

Today is Becky's birthday.  I'll refrain from revealing her age, as that would be detrimental to my health.  (She has a black belt in Kung Fu, you know)

posted on Monday, August 23, 2004 6:51:34 AM (Pacific Standard Time, UTC-08:00)  #    Comments [3]
 Saturday, August 14, 2004

I've been playing with the new membership framework in ASP.net 2.0.  The existence of this, and other nice things like the login controls are fantastic, but it really lacks the polish of other areas of the new framework.  Here's some constructive feedback:

The MembershipProvider looks like a pretty well designed base class, but it should implement more of its interface by default.  For instance, when creating your own provider, you're forced to implement Initialize, which configures the instance for the configuration in the web.config.  Initialize is defined in ProviderBase, but there should be a default implementation in MembershipProvider that at least configures the values for the required properties such as EnablePasswordReset and such.  I ended up using the Reflector to look at the AccessMembershipProvider to implement this method.  Also, the majority of the proeprties should have default implementations as well.

The documentation for implementing a MembershipProvider is also pretty inconsistent.  Some of the methods are supposed to throw exceptions for failures, some of them return booleans for success/failure (which I thought had been deemed not a good idea), and some of them say they should throw exceptions, but also return a boolean.

The MembershipUser class is also pretty good, but its ISerializable implementation is weird.  Deserializing one would leave it in an unusable state since its _Provider field would be uninitialized, and since it's not settable, its useless.

I love the idea and the ease of which you can use the membership concept. (The default “just works”) But to create the “pit of success”, there are some things to address and I hope someone is addressing them.

[UPDATE] Brad Abrams helped me get this feedback to the right people.  Thanks Brad.  It makes me feel really good about the direction of the .NET and Microsoft as a whole to know I can get my feedback to the people who need to hear it.  I may be making incorrect assumptions or drawing the wrong conclusions, but chances are if I am, then others are too.

posted on Saturday, August 14, 2004 9:59:15 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Friday, August 13, 2004

The HD broadcast of the olympics just started...beautiful.  Just beautiful.

One weird thing though.  The audio keeps jumping from Dolby Digital 3/0 to 2/0 every few minutes.  I'm trying to figure out if it's a reception issue.  Anyone else having trouble?  If not, what are you getting?

[Update] I just went outside and unplugged all my cables except my cable modem and the livingroom connection.  I've got full Dolby Digital 3/2.1 now.  yeah!

posted on Friday, August 13, 2004 4:25:47 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Thursday, August 12, 2004

The managed API for the windows performance counters is great.  It was just what I needed to track down some memory issues at work, and now I've got real-time information about what's going on.  It's much simpler than trying to use them with the old school api.  However, I need some more guidance on the usage pattern for creating and deleting the categories and counter definitions.  Are those things that should be part of an install/uninstall procedure, or should they be done on startup/exit of the program?  What kind of overhead should I expect in constructing/incrementing/disposing them?  The counters implement IDisposable, which makes me want to dispose them quickly.

Maybe some spelunking with the Reflector will shed some light.  I'll keep you posted.  In the meantime, feel free to share your experiences with performance counters in the CLR.

[Update] Duh.  I ran across System.Diagnostics.PerformanceCounterInstaller the other day.  Looks like that's how you should install them.  I love the installers as well.

posted on Thursday, August 12, 2004 10:59:44 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Tuesday, August 10, 2004

I ran across the new web-based MSN Messenger the other day.  I haven't had access to messenger from work in a long time.  The old version didn't work through our firewall, so I developed a local proxy to tunnel the traffic.  Then they started blocking that traffic outbound.  Then they rolled out a crappy customized version of it to collaborate in-house which couldn't go outside the firewall.  But this web-based one works perfectly through the firewall, so I am once again available while at work...within reason of course.

posted on Tuesday, August 10, 2004 8:53:07 AM (Pacific Standard Time, UTC-08:00)  #    Comments [1]
 Sunday, August 08, 2004

Last night, I upgraded to XP service pack 2.  It went very smoothly.  The new wireless networking support is fantastic.  I can finally unload the annoying software that came with the laptop to manage the networks.

I'm a little dissapointed with the firewall.  It adds a few new features, but still doesn't seems as configurable as I'd like.  We'll see...some more time with it may change my mind.

It was a very simple, smooth install.  I would let any of my family or friends attempt it by themselves, and probably will.

posted on Sunday, August 08, 2004 9:25:59 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Saturday, August 07, 2004

I mostly finished up the work I started last week on the back wall of the house.  Thanks a bazillion to Mom and Dad for helping out.  A few things I did smarter this week were to use a heavy duty car jack to lift the heavy hardi-panel panels into place.  They are really heavy, and since they are about .5“ thick, they really cut into your hands.  The jack worked amazingly well.  Thanks to my co-worker Mark Leech for such an ingenious, yet somehow common sense idea.

I'll see about getting some pictures up later when I'm not so sweaty and tired.

posted on Saturday, August 07, 2004 12:20:20 PM (Pacific Standard Time, UTC-08:00)  #    Comments [2]
 Tuesday, August 03, 2004

Well, i just couldn't wait.  I played Peasant's Quest and won.  It was pretty fun.  I wonder if anyone got higher than 135.

posted on Tuesday, August 03, 2004 6:20:35 PM (Pacific Standard Time, UTC-08:00)  #    Comments [3]