Notes from Daily Encounters with Technology RSS 2.0
 
# Tuesday, February 28, 2006

One of the most common tasks when analyzing performance and optimizing code is measuring the time it takes to execute the code in question. Before .NET 2.0 you had to develop you own high resolution timer for the job by wrapping the unmanaged calls to QueryPerformanceCounter and QueryPerformanceFrequency.

I kept using the same class in .NET 2.0 but just the other day I stumbled across the Stopwatch class in the System.Diagnostics namespace. It implements the same high resolution timer functionality out of the box, so there’s no need to use unmanaged calls to achieve it anymore.

And the basic usage couldn’t be simpler:

using System.Diagnostics;
// ...
Stopwatch sw = new Stopwatch();
sw.Start();
// do some processing here
sw.Stop();
Debug.WriteLine("Time elapsed:" + sw.ElapsedMilliseconds.ToString());

One wonders what other hidden treasures lie in the class library yet to be discovered.
Tuesday, February 28, 2006 10:21:00 PM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Development | .NET
# Friday, February 24, 2006

I’ve spent a few hours today hunting down a mysterious bug which caused the program to keep reporting failed connections to database server although it was already available for hours. In the end it was a problem of incomplete exception handling but it’s interesting how the problem manifested itself. Let’s look at the following sample code.

using System;
using System.Collections.Generic;
using System.Text;

namespace DamirsCorner.Samples.StaticConstructor
{
   class Program
   {
      static string source;

      class Static
      {
         static Guid problem;

         static Static()
         {
            // will cause an exception if not a valid guid
            problem = new Guid(Program.source);
         }

         public static void Write()
         {
            // will only succeed after successful type initialization
            Console.WriteLine("Success!");
         }
      }

      static void Main(string[] args)
      {
         // setup invalid GUID source value
         source = String.Empty;
         Console.WriteLine("Invalid source value: \"" + source + "\"");
         try
         {
            // type initializer will fail here
            Static.Write();
         }
         catch (Exception e)
         {
            Console.WriteLine("Exception: " + e.Message + "\n\t" + e.InnerException.Message);
         }
         // setup valid GUID source value
         source = Guid.Empty.ToString();
         Console.WriteLine("Valid source value: \"" + source + "\"");
         try
         {
            // type initializer should succeed here
            Static.Write();
         }
         catch (Exception e)
         {
            Console.WriteLine("Exception: " + e.Message + "\n\t" + e.InnerException.Message);
         }
         Console.ReadKey();
      }
   }
}

Ok, there’s no database access here but just imagine that the Guid constructor call is the database access attempt. As you can see, the first call simulates that the server is down while at the second call the server is back up. Keeping that in mind the first call should fail while that second one shouldn't. (For those of you not familiar with static constructors: they get executed before the first (static or instance) property access or method call. As such they take care of type initialization.) Let’s take a look at the program output then.

Invalid source value: ""
Exception: The type initializer for 'Static' threw an exception.
        Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
Valid source value: "00000000-0000-0000-0000-000000000000"
Exception: The type initializer for 'Static' threw an exception.
        Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).

Obviously both calls have failed. Why is that so?

It turns out that the static constructors are executed exactly once. If they throw an exception, it gets wrapped as an InnerException of the TypeInitializationException. Any attempts to use this class afterwards don’t cause the constructor to execute again, but just make it throw the same exception once again. Therefore the method call still reports an invalid GUID value (or in my case failed database connection attempt) although the problem has already been remedied. This makes the class effectively unusable within the AppDomain.

The lesson to be learned: no matter what you’re doing in the static constructor, never allow it to throw an exception unless the problem is indeed fatal and you intend to quit the program immediately. In all other cases provide reasonable defaults and handle changed circumstances elsewhere in the code.

You can find some additional technical details in Chris Brumme’s blog entry.

Friday, February 24, 2006 12:19:47 AM (Central European Standard Time, UTC+01:00)  #    Comments [1] - Trackback
Development | .NET
# Sunday, February 12, 2006

It’s almost half a year since security update 896358 has been released which prevents viewing HTML help (CHM) files from network drives. It should be noted that the file actually can be opened only the containing HTML files don’t get displayed.

Until now it wasn’t really an issue for me as I was always opening help files from local disks. But in the last few weeks I am managing help development at work and with company policy having latest files on file server shares I keep having to copy the files to my local disk before testing and reviewing them which soon gets annoying.

To avoid the repetitive tedious task of copying files around I decided to look more closely into the issue. It turned out that you can set the maximum trusted zone in the registry to avoid the problem. Since I trust the complete local network zone at work I raised the trust level by adding the following to the registry:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\HTMLHelp\1.x\ItssRestrictions]
"MaxAllowedZone"=dword:00000001

Problem solved.

Sunday, February 12, 2006 10:40:34 AM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Software | Windows
# Monday, January 23, 2006

When I started to work on my Master’s thesis I first had to find a good source of articles from science magazines and journals and proceedings from conferences related to my research field. Since I didn’t want to spend most of the time in the faculty library which would be difficult anyhow due to strange hours I used to work on my thesis, I was looking for an online source.

The obvious choice was Google Scholar but it soon turned out that although its searching capabilities are great, it still doesn’t give access to the full text of the articles. After I realized that there’s no way to get enough material for free I decided to join the ACM (Association for Computing Machinery) as a professional member and go for the additional ACM Digital Library subscription. This gave me access most of the articles they ever published which was almost everything I needed.

At the end of the month it’ll be a year since I’ve done this and it was time to renew my membership. My first thought was to just let it go since I’ve already finished the thesis in the meantime. But I remembered having read in one of their newsletters that their professional members were given access to a part of the Safari Bookshelf so I decided to take a look at what exactly they offered. It turned out that every ACM member has access to their Professional Development Centre which includes 500 online books from the Safari Enterprise Library, 395 online books from Books24x7 and over 1000 online courses from ThomsonNETg. A more detailed look revealed that there’s a lot in there that would be of interest to me.

Therefore I’ve just renewed my subscription for another year, this time without the ACM Digital Library access because I certainly won’t need it unless I decided to write a Ph. D. thesis which surely won’t happen within the next 12 months. It’s well worth it even if you’re only about to read a selection of the books but there are other membership benefits as well.

One more thing: if you come from Slovenia or any other "economically developing country", don’t forget to take advantage of the discounts. You could save even more.

Monday, January 23, 2006 11:59:12 PM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Personal | Education
# Thursday, January 19, 2006

The problem is pretty straightforward: the web site redesign causes the structure to change, thus the old addresses become invalid. Since you don’t want the users to get the dreaded error 404: Object not found, there are a couple of options available to you (if you’re using IIS – Internet Information Services, that is).

You could just change the error page to match the style of your web site and inform the visitor about the now missing page or just make the redirection to your new starting page. This is a bit unfriendly to the visitors if you kept the old content since they have to find it themselves. It would certainly be better to redirect them directly to the new address of the old content. But still it’s not a bad idea to do this. It’s an easy way to keep the users on your website even when they encounter invalid URLs by whatever reason. Just open up the Custom Errors tab of the virtual directory or web site properties and set the desired URL for the error 404. But don’t forget that you have to enter the complete path starting from the root of the site, for example: "/mydirectory/myurl.html".

If you want to make a different redirection for each page you could just keep the old pages but instead of having any actual content they would just make a redirection to the correct new address. This solution has two problems:

  • It’s difficult to maintain if you have many pages.
  • You’re stuck with the client side redirection, i.e. meta refresh tag.

To make the redirection server side you could use the redirect options on the Home Directory tab of the virtual directory or web site properties. But they have some serious limitations and tend not to work as expected, even more so because the documentation doesn’t explain them very well. But there’s no reason to worry, I have a better solution for you. Setup a special 404 URL on the Custom Errors tab as already suggested. But this time use an asp or aspx page for it. The supplied query string (Request.QueryString) contains the missing URL which you can parse out and use to determine the correct new address corresponding to it. For a few pages a simple select or switch clause will do but nothing prevents you from having the mappings stored externally, in a special file or a database table for example. All that’s left is to make a Response.Redirect to the new address.

There’s one more thing to take care of. If you moved your site to a new subdirectory and chose the last suggested solution, don’t forget to setup a similar simple starting page which just redirects the visitors to the new starting page. Trying to open the site without this page will namely cause an error 403: Forbidden, because a directory listing will be attempted which you have (hopefully) prevented.

Thanks go to Peter Forret for some of the ideas I used to make this work when redesigning my page.

Thursday, January 19, 2006 11:35:50 PM (Central European Standard Time, UTC+01:00)  #    Comments [1] - Trackback
Development | ASP.NET | Software | Windows
Sponsored Ads

About Me

Damir Arh

Microsoft Certified Professional

View Damir Arh's profile on LinkedIn

Profile for ExAmigan

ExAmigan

Twitter
Damir's Corner: Avoiding Queue Starvation in CruiseControl.NET http://goo.gl/fb/G52YB 1 day ago
RT @aleksj: From http://last.fm/robots.txt: Disallow: /harming/humans, Disallow: /ignoring/human/orders, Disallow: /harm/to/self #asimov 2 days ago
Eagle Eye on DVD was a pleasant surprise. It passed under my radar when it was first released. 5 days ago
Multiple RTM gadgets in iGoogle suddenly can't show different lists anymore http://digs.by/aD5AbJ 6 days ago
Notifications for new projects in CCTray are a nice new feature of #ccnet 1.5 7 days ago
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

All Content © 2010, Damir Arh, M. Sc. Send mail to the author(s) - Privacy Policy - Sign In
Based on DasBlog theme 'Business' created by Christoph De Baene (delarou)