Lazy task execution in .NET C#

Tasks in .NET can be executed lazily, i.e. only at the time when the result is needed. This may never come in certain situations. You can build tasks that are not executed until a lazy variable is required. The lazy variable is not initialised until it is read.

You can construct a lazy task in two separate steps:

Func<string> functionBody = new Func<string>(() =>
{
	Console.WriteLine("Function initialiser starting...");
	return "Some return value from the function initialiser";
});

Lazy<Task<string>> lazyInitialiser = new Lazy<Task<string>>
	(() =>
		Task<string>.Factory.StartNew(functionBody)
	);

Here we first create a function which we then pass to the Lazy constructor. You can specify the type of object that will be lazily initialised. One of the overloaded constructors of Lazy accepts a Func of Task of T which will be the initialisation function. Task.Factory.StartNew comes in handy here as we can supply our function.

You can achieve the same initialisation in one step as follows:¨

Lazy<Task<string>> inlineLazyInitialiser = new Lazy<Task<string>>(
	() => Task<string>.Factory.StartNew(() =>
	{
		Console.WriteLine("Inline initialiser starting...");
		return "Some return value from the inline lazy initialiser.";
	}));

We read the results as follows:

Console.WriteLine("Calling function initialiser within Lazy...");
Console.WriteLine(string.Concat("Result from task: ", lazyInitialiser.Value.Result));

Console.WriteLine("Calling inline lazy initialiser...");
Console.WriteLine(string.Concat("Result from task: ", inlineLazyInitialiser.Value.Result));

View the list of posts on the Task Parallel Library here.

Continuing with an attached child Task in .NET C#

A child Task, a.k.a a nested Task, is a Task that’s started within the body of another Task. The containing Task is called the parent.

We saw here how to create an attached child Task and here how to create continuation tasks. We can now marry the two concepts. If you don’t know what they are then make sure to check out those posts as well.

This is how you attach a child task to a parent, create a continuation task to the child task and attach the continuation task to the parent as well:

Task parent = Task.Factory.StartNew(() =>
{
	Console.WriteLine("Starting child task...");

	Task child = Task.Factory.StartNew(() =>
	{
		Console.WriteLine("Child running. Going to sleep for a sec.");
		Thread.Sleep(1000);
		Console.WriteLine("Child finished and throws an exception.");
		throw new Exception();
	}, TaskCreationOptions.AttachedToParent);

	child.ContinueWith(antecedent =>
	{
		// write out a message and wait
		Console.WriteLine("Continuation of child task running");
		Thread.Sleep(1000);
		Console.WriteLine("Continuation finished");
	}, TaskContinuationOptions.AttachedToParent
		| TaskContinuationOptions.OnlyOnFaulted);				
});

try
{
	Console.WriteLine("Waiting for parent task");
	parent.Wait();
	Console.WriteLine("Parent task finished");
}
catch (AggregateException ex)
{
	Console.WriteLine("Exception: {0}", ex.InnerException.GetType());
}

Note the TaskCreationOptions parameter in the StartNew method: AttachedToParent. We also introduce a filter to the continuation task: run it only if the task before that, i.e. the ‘child’ has faulted. Which will happen as we throw an exception in the body of ‘child’.

If you run this code the you’ll see that the exception thrown by the child task is caught in the try-catch block. The original exception has been packaged within an AggregateException. Also, the Wait() method will wait for the parent task to finish which in turn waits for the child to finish. So Wait() indirectly waits for any attached children the parent Task may have. Finally, you’ll see that the continuation task runs as ‘child’ has faulted.

View the list of posts on the Task Parallel Library here.

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

ARCHIVED: Bite-size insight on Cyber Security for the not too technical.