Thursday, February 9, 2012

Know what is executing when and where...

If we run this test, it throws an uncaught exception from the thread pool. Uncaught exceptions from the thread pool will crash your app.

The key to this is that the lambda is not executed here and now. The Lambda is passed to the thread pool.
The thread pool executes it, but only after we have set our classWithFunction member variable to null.

 class ClassWithFunction  
 {  
   public void fn()  
   {  
     System.Console.WriteLine("Hello World");  
   }  
 }  
   
 ClassWithFunction classWithFunction = new ClassWithFunction();  
   
   
 [Test]  
 public void testThreadPool()  
 {  
   ThreadPool.QueueUserWorkItem(state => classWithFunction.fn());  
   
   classWithFunction = null;  
   
   Thread.Sleep(2000);  
 }  
   


If you consider the Lambda in terms of a function, it all becomes a whole lot clearer. By the time ThreadPoolFunction is called, classWithFunction is null.
This is referred to as a modified closure. The Lambda does not get a copy of our variable, it actually uses our variable in place.

 class ClassWithFunction  
 {  
   public void fn()  
   {  
     System.Console.WriteLine("Hello World");  
   }  
 }  
   
 ClassWithFunction classWithFunction = new ClassWithFunction();  
   
 [Test]  
 public void testThreadPool()  
 {  
   ThreadPool.QueueUserWorkItem(ThreadPoolFunction);  
   
   classWithFunction = null;  
   
   Thread.Sleep(2000);  
 }  
   
 private void ThreadPoolFunction(object state)  
 {  
    classWithFunction.fn();  
 }  


And if you look closely, you will see that this IS different and it works quite nicely. Of course, the downside of this as a solution is that someone will surely come along and remove the "unnecessary" temporary variable.

 [Test]  
 public void testThreadPool()  
 {  
   ClassWithFunction tempClassWithFunction = classWithFunction;  
   ThreadPool.QueueUserWorkItem(state => tempClassWithFunction.fn());  
   
   classWithFunction = null;  
   
   Thread.Sleep(2000);  
 }  


Perhaps it would be better to move up to .net 4 and use the Parallel Task Library instead.

No comments:

Post a Comment