Sunday, 23 April 2017

TPL 04 ContinueWith

When a task is started and a result is requested the calling thread halts until the task completes.

using System;
using System.Threading.Tasks;

namespace pc.tplEample03
{
    class Program
    {
        static Random rnd = new Random(DateTime.Now.Millisecond);
        static void Main(string[] args)
        {
            var tasks = new Task<int>[5];
            for (int i = 0; i < tasks.Length; i++)
            {
                tasks[i] = new Task<int>(Square, i);
                tasks[i].Start();
            }

            foreach(var t in tasks)
                Console.WriteLine(t.Result);
        }

        static int Square(object o)
        {
            int num = Convert.ToInt32(o);
            int delay = rnd.Next(1000, 5000);
            Task.WaitAll(Task.Delay(delay));
            return num * num;
        }
    }
}

in the above example we create and start all of our tasks at the same time, but we have to wait for them sequentially to view the results, thus if the first task takes a long time, the other four may very well be complete but because we're waiting for the first task to finish we can't see the results of the following tasks

in comes the continuewith function, the continue with lets us give our tasks a function to do once they complete.

using System;
using System.Threading.Tasks;

namespace pc.tplEample03
{
    class Program
    {
        static Random rnd = new Random(DateTime.Now.Millisecond);
        static void Main(string[] args)
        {
            var tasks = new Task<int>[5];
            for (int i = 0; i < tasks.Length; i++)
                tasks[i] = Task.Factory.StartNew(Square, i).ContinueWith(OutPut);

            Console.ReadKey();

            foreach (var t in tasks)
                Console.WriteLine(t.Result);
        }

        static int Square(object o)
        {
            int num = Convert.ToInt32(o);
            int delay = rnd.Next(1000, 5000);
            Task.WaitAll(Task.Delay(delay));
            return num * num;
        }

        static int OutPut(Task<int> tr)
        {
            var result = tr.Result;
            Console.WriteLine(result);

            return result;
        }
    }
}

so with our refactored code above we get see our results without blocking the calling thread and as they are resolved.