RSS

Captured Variables in C# Inside Lambda Expressions(Closures)?

29 Jun

One of the great additions to C# in recent past is async processing abstractions via “Task” object which is defined in System.Threading.Tasks. While I was playing with some of the features of it what I have noticed was captured variables in lambda expressions which you will see much analogous to JavaScript closures.Initially my code was like this,

Action<Task> continuationAction = t => Console.WriteLine("Task Status:" + t.Status);
			var cts = new CancellationTokenSource();
			Task mytask = default(Task);
			for (int i = 0; i < 10; i++)
			{
				mytask = Task.Factory.StartNew(() => {
					 Console.WriteLine("Starting Task NO:" + i);
					 Thread.Sleep(1000);
					 Console.WriteLine("Finishing Task NO:" + i);
				 }).ContinueWith(continuationAction, cts.Token);
			}

			mytask.Wait();
			Console.Read(); 

As you can see in the for loop initially I was expecting that Action lambda passed to Task.Factory.StartNew would print 1 to 10 for the places where variable “i” is being referred which was not the case it printed “10” for all the places where variable “i” was being referred. So reason for this is in even before the first task was started to perform the outer for loop had been completed this might be because thread initializing overhead which means stack for variable “i” updated with 10 so each task will print its value which is 10. You can put some wait in outer for loop and this can be easily proved. To prevent this sort of captured variable “i” I just simply copied “i” to another stack variable and referred that inside the Action which gave me 1 to 10 when variable “i” referred inside the action.


Action<Task> continuationAction = t => Console.WriteLine("Task Status:" + t.Status);
			var cts = new CancellationTokenSource();
			Task mytask = default(Task);
			for (int i = 0; i < 10; i++)
			{
				int i1 = i;
				mytask = Task.Factory.StartNew(() => {
					 Console.WriteLine("Starting Task NO:" + i1);
					 Thread.Sleep(1000);
					 Console.WriteLine("Finishing Task NO:" + i1);
				 }).ContinueWith(continuationAction, cts.Token);
			}

			mytask.Wait();
			Console.Read();

So the interesting point to note is in lamda expressions semantecs, outer variables referenced by a lambda expression will be captured. These captured variables evaluated at runtime or when the lambda expression invoked not when they were defined. So lambda expression seems like a closure in javascript?

Advertisements
 
Leave a comment

Posted by on June 29, 2013 in .NET, C#

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: