Exception Management in Threads

Exception Management is a topic near and dear to me personally, primarily because of the lack of understanding of most developers (that I have come across). There is an interesting change in the .NET 2.0 CLR on how it manages unhandled exceptions in a thread. If you write multi-threaded apps then this is important for you to understand. If you don’t write multi-threaded apps today, but I presume you would soon, then this is a good learning exercises.

In .NET 2.0 the CLR allows unhandled exceptions in threads to proceed naturally – which in many cases probably means that the application will terminate. For certain cases (listed below) where exceptions are used for controlling program flow, the CLR does provide a backstop for unhandled exceptions in threads. Note, the CLR terminated the threads in these cases and does not propagate the exception further.

  • Abort() is called causing a ThreadAbortException.
  • AppDomain (in which the thread is running) is being unloaded, causing a AppDomainUnloadedException.
  • The Host process (or CLR) terminates the thread via an internal exception.

This is a significant change from .NET v1.x where there is no concept of a Unhandled Exception in many situations such as a Thread pool. If an unhandled exception is thrown, the runtime prints that to the console and then returns the thread to the thread pool. Also, if an unhandled exception occurs in the Start() method of a Thread class, the runtime again prints the exception stack trace to the console and then gracefully terminating the thread. Lastly, if an unhandled exception occurs on a Finalizer thread, the trace is written to the console, and the finalizer thread is allowed to resume!

Needless to say, if you have code currently designed for this, it will break in .NET 2.0 and you would need to change your implementation. As a temporary workaround you can choose your app to still use the old style from v1.x by setting the flag in the runtime section, but this should be strictly till such a time you can port the code over to the new version:

<legacyUnhandledExceptionPolicy enabled=”1″/>

If you got MSDN installed for VS 05, you can read more here then.

Delhi Airport, Fog and Dilbert

I don’t know if I should laugh or be worried (when I fly into Delhi next month), but it seems the brand-spanking-new ILS landing system for Delhi Airport is not only setup correctly, there is no one trained to use it (yet), with some people in the government claiming success. It seems like a page out of Dilbert and seems like déjà vu when it comes to IT projects.

Execution Context

It is quite interesting to see how many people don’t understand the basics of threading, while it is a difficult topic (especially to debug), and it is not the silver bullet for all the problems, but it sure is quite handy for certain things. With the inevitable shift to multi-core CPU’s and the release of Vista to take better opportunity of these extra power, more applications in the future should be ready to exploit them. Which makes it quite important for the average developer to start playing and understanding this.

If you are new to this, one of the classes I would recommend reading up on is called ExecutionContext class. This class essentially is the equivalent of the COM Apartment (from the good old COM days). This class provides a single container for all information relevant to a logical thread of execution which includes security context, call context, synchronization context, localization context, and transaction context. You cannot change context of the thread (to which a ExecutionContext is attached), you can only copy it to another thread. If you do try and copy it you will get an Exception.

Here is an example from MSDN on how to use this (also testing the new CopyAsHTML Addin):

    1 using System;

    2 using System.Threading;

    3 using System.Security;

    4 using System.Collections;

    5 using System.Security.Permissions;

    6 using System.Runtime.Serialization;

    7 using System.Runtime.Remoting.Messaging;

    8 

    9 namespace Contoso

   10 {

   11     class ExecutionContextSample

   12     {

   13         static void Main()

   14         {

   15             try

   16             {

   17                 Console.WriteLine(“Executing Main in the primary thread.”);

   18                 FileDialogPermission fdp = new FileDialogPermission(

   19                     FileDialogPermissionAccess.OpenSave);

   20                 fdp.Deny();

   21                 // Capture the execution context containing the Deny.

   22                 ExecutionContext eC = ExecutionContext.Capture();

   23 

   24                 // Suppress the flow of the execution context.

   25                 AsyncFlowControl aFC = ExecutionContext.SuppressFlow();

   26                 Thread t1 = new Thread(new ThreadStart(DemandPermission));

   27                 t1.Start();

   28                 t1.Join();

   29                 Console.WriteLine(“Is the flow suppressed? “ +

   30                     ExecutionContext.IsFlowSuppressed());

   31                 Console.WriteLine(“Restore the flow.”);

   32                 aFC.Undo();

   33                 Console.WriteLine(“Is the flow suppressed? “ +

   34                     ExecutionContext.IsFlowSuppressed());

   35                 Thread t2 = new Thread(new ThreadStart(DemandPermission));

   36                 t2.Start();

   37                 t2.Join();

   38                 // Remove the Deny.

   39                 CodeAccessPermission.RevertDeny();

   40                 // Capture the context that does not contain the Deny.

   41                 ExecutionContext eC2 = ExecutionContext.Capture();

   42                 // Show that the Deny is no longer present.

   43                 Thread t3 = new Thread(new ThreadStart(DemandPermission));

   44                 t3.Start();

   45                 t3.Join();

   46 

   47                 // Set the context that contains the Deny.

   48                 // Show the deny is again active.

   49                 Thread t4 = new Thread(new ThreadStart(DemandPermission));

   50                 t4.Start();

   51                 t4.Join();

   52                 // Demonstrate the execution context methods.

   53                 ExecutionContextMethods();

   54                 Console.WriteLine(“Demo is complete, press Enter to exit.”);

   55                 Console.Read();

   56             }

   57             catch (Exception e)

   58             {

   59                 Console.WriteLine(e.Message);

   60             }

   61         }

   62         // Execute the Demand.

   63         static void DemandPermission()

   64         {

   65             try

   66             {

   67                 Console.WriteLine(“In the thread executing a Demand for “ +

   68                     “FileDialogPermission.”);

   69                 new FileDialogPermission(

   70                     FileDialogPermissionAccess.OpenSave).Demand();

   71                 Console.WriteLine(“Successfully demanded “ +

   72                     “FileDialogPermission.”);

   73             }

   74             catch (Exception e)

   75             {

   76                 Console.WriteLine(e.Message);

   77             }

   78         }

   79 

   80         static void ExecutionContextMethods()

   81         {

   82             // Generate a call context for this thread.

   83             ContextBoundType cBT = new ContextBoundType();

   84             cBT.GetServerTime();

   85             ExecutionContext eC1 = ExecutionContext.Capture();

   86             ExecutionContext eC2 = eC1.CreateCopy();

   87             Console.WriteLine(“The hash code for the first execution “ +

   88                 “context is: “ + eC1.GetHashCode());

   89 

   90             // Create a SerializationInfo object to be used for getting the

   91             // object data.

   92             SerializationInfo sI = new SerializationInfo(

   93                 typeof(ExecutionContext),

   94                 new FormatterConverter());

   95 

   96             eC1.GetObjectData(

   97                 sI,

   98                 new StreamingContext(StreamingContextStates.All));

   99 

  100             LogicalCallContext lCC = (LogicalCallContext)sI.GetValue(

  101                 “LogicalCallContext”,

  102                 typeof(LogicalCallContext));

  103 

  104             // The logical call context object should contain the previously

  105             // created call context.

  106             Console.WriteLine(“Is the logical call context information “ +

  107                 “available? “ + lCC.HasInfo);

  108         }

  109     }

  110 

  111 

  112     // One means of communicating between client and server is to use the

  113     // CallContext class. Calling CallContext effectivel puts the data in a thread

  114     // local store. This means that the information is available to that thread

  115     // or that logical thread (across application domains) only.

  116     [Serializable]

  117     public class CallContextString : ILogicalThreadAffinative

  118     {

  119         String _str = “”;

  120 

  121         public CallContextString(String str)

  122         {

  123             _str = str;

  124             Console.WriteLine(“A CallContextString has been created.”);

  125         }

  126 

  127         public override String ToString()

  128         {

  129             return _str;

  130         }

  131     }

  132 

  133     public class ContextBoundType : ContextBoundObject

  134     {

  135         private DateTime starttime;

  136 

  137         public ContextBoundType()

  138         {

  139             Console.WriteLine(“An instance of ContextBoundType has been “ +

  140                 “created.”);

  141             starttime = DateTime.Now;

  142         }

  143         [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.Infrastructure)]

  144         public DateTime GetServerTime()

  145         {

  146             Console.WriteLine(“The time requested by a client.”);

  147             // This call overwrites the client’s

  148             // CallContextString.

  149             CallContext.SetData(

  150                 “ServerThreadData”,

  151                 new CallContextString(“This is the server side replacement “ +

  152                 “string.”));

  153             return DateTime.Now;

  154         }

  155     }

  156 

  157 }

CopySourceAsHTML For Visual Studio 2005

If you read the Ten Essential Tools Visual Studio Add-Ins Every Developer Should Download Now in MSDN Mag, then you are aware of CopySourceAsHTML which unfortunately works for only Visual Studio 2003. But if you are using VS 2005, fear not as Derick Bailey has updated the add-in. There is no installer (yet), but you can download the code and build it, which will locally also install the add-in.

Belkin Screen Shots

As a few of you had requested below are links to some screen shots for the Belkin router.

Could not resolve type [your-type-here], contract cannot be created.

If you are writing an Indigo service and you can an error for something like the one shown below, then essentially you change the interface (i.e. your contract) you implemented in Indigo (now WCF), but forgot to change the interface in the web.config.

<endpoint contract=MY-TYPE-HEREbinding=wsHttpBinding/>

<snip>
Could not resolve type IMyService, contract cannot be created. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: Could not resolve type IMyService, contract cannot be created.

Source Error: An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:
[InvalidOperationException: Could not resolve type ICalculators, contract cannot be created.]
</snip>

Funny Error Msg

I had send an email to a friend and based on the email bouncing I know I had the old email address; but this is one of the funniest error messages I have receive in a long time, it did put a smile on the face.

Hi. This is the qmail-send program at mantramail.com.
I’m afraid I wasn’t able to deliver your message to the following addresses.
This is a permanent error; I’ve given up. Sorry it didn’t work out.

You could be an engineer:

  • If you introduce your wife as “mylady@home.wife”
  • If you have more toys than your kids
  • If you need a checklist to turn on the TV
  • If you can remember 7 computer passwords but not your anniversary
  • If you think that when people around you yawn, its because they didn’t get enough sleep
  • If your wife hasn’t the foggiest idea what you do at work
  • If you spend more on your home computer than your car

Read more here
.