Create a lazy task in .Net

Lazy initialization is a practice whereby you only load or initialize an object when you first need it. This means the object initialization is deferred until the first time it’s used.

In our development world this can be extremely beneficial when we have expensive resources and or components to initialize like a database connection or accessing the file system to read, write or edit a file.

Framework 4.0 introduced the Lazy<T> Type, This type allows us to create an object and defer its initialization until we need it (Singleton Pattern type construct). One of the main advantage of the Lazy<T> is the ability to specify a Func<T> to server as factory design pattern method as well as specifying if the Lazy<T> should be treated as a thread safe object or not.

Here is an example to demonstrate lazy tasks in C#:

Func<string, string> TextFileReader = (fileName ) =>
            {
                var stringBuilder = new StringBuilder();
                using (var streamreader = new StreamReader(fileName))
                {
                    string line;
                    while ((line = streamreader.ReadLine()) != null)
                    {
                        stringBuilder.AppendLine(line);
                    }
                }
                return  stringBuilder.ToString();
            };

There is nothing fancy or over complicated here; We have a func that accept a string (filename) and return a string (the content of the file).

The next snippet will create a Lazy<task<string>> to read the file and use it's content:

var lazyreaderTask = new Lazy<Task<string>>(() =>
           Task<string>.Factory.StartNew(() =>
           TextFileReader(@"E:\Demo.txt")), true);
           Console.WriteLine("Is value created? {0}", lazyreaderTask.IsValueCreated);
           Console.WriteLine("Result from task {0}", lazyreaderTask.Value.Result);
           Console.WriteLine("After exectuting the task {0}", lazyreaderTask.IsValueCreated);

If you comment line 5 in the above snippet, you will notice that the lazy task hasn't executed (IsValueCreated=false).Lazy<T> will executes only when is Value is called.

The final thing to note here is the true parameter on line 3, this parameter is used to set the lazy object as thread safe

Comments (3) -

can we execute these lazy tasks in parallel?

Sure, you can Mike,
Try something like this (You will have to check my syntax as I don't have access to an IDE)
//first warp the Lazy<Task<string>> in an action
Action lazyTaskWrapper = (() =>
            {
                var lazyreaderTask = new Lazy<Task<string>>(() =>
                Task<string>.Factory.StartNew(() =>
                TextFileReader(@"E:\Demo.txt")), true);
                Console.WriteLine("Is value created? {0}", lazyreaderTask.IsValueCreated);
                Console.WriteLine("Result from task {0}", lazyreaderTask.Value.Result);
                Console.WriteLine("After exectuting the task {0}", lazyreaderTask.IsValueCreated);
            });
            //then call the wrapper using Parralele for
            Parallel.For(1, 10, ((_) =>
            {
                lazyTaskWrapper();
            }));

Wow....copied and pasted and code built without any modifications.
Do you have any book recommendations for parallel C#?

Add comment