Task in C# Extended is the continuation of my previous article on Tasks, where we discussed about the basic understanding of Tasks and its usage. Continuing with that, here we will discuss some more functionality and behavior of Task.
How to wait for Tasks to complete ?
As you know that Task runs asynchronously on a thread from the Thread Pool . The thread starts task execution asynchronously along with the main application thread as soon as it has been instantiated and invoked.
We also see an example in our previous discussion on Task, where both threads (Main and Child) started its execution simultaneously (asynchronously), the Main thread didn’t wait for the Child thread to complete. The Child thread continued its execution even after completion of Main thread execution.
In cases, where you want your main application thread execution to wait until other child Tasks completes its execution, then you can do that in Task by using Wait() method.
Example – Waiting for Task to complete :
In below example, we have created a method as PrintOddEvenNumbers that prints odd and even numbers. In the Main method, we have created a task instance Task t = new Task(PrintOddEvenNumbers); and then invoking it by calling t.start() .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
using System; using System.Threading.Tasks; namespace TaskInCshap { class Program { static void Main(string[] args) { //Create a task instance Task t = new Task(PrintOddEvenNumbers); t.Start(); //Waiting for child thread to complete t.Wait(); Console.WriteLine("In Main Method, Finished work on thread : {0}", System.Threading.Thread.CurrentThread.ManagedThreadId); Console.Read(); } public static void PrintOddEvenNumbers() { Console.WriteLine("Even and Odd numbers less than 10"); //Print even numbers for (int i = 0; i <= 10; i++) if (i % 2 == 0) Console.WriteLine("Even Number : {0}", i); //Print odd numbers for (int i = 0; i <= 10; i++) if (i % 2 != 0) Console.WriteLine("Odd Number : {0}", i); Console.WriteLine("In Child Method, Finished work on thread : {0}", System.Threading.Thread.CurrentThread.ManagedThreadId); } } } |
In the above example, we have used t.Wait() method for Task t object. Which will make the Main thread to wait until the Child thread finishes its execution.
When we run the above program, we will get below output.
If you notice in the above output console, here the the Main thread waits for the Child thread to finish its execution.
Get return value from Tasks ?
We can also return a value from a Task object, In that case, we have to specify the return type as a type parameter to the Task object as Task<T> , where T being the type.
Example : Return value from a Task :
In below example, we have created a method as SumOfAllNumber that takes an integer array as input and calculates the sum of values present in the array, finally returns the calculated sum value. In the Main method, we have created a task instance Task<int> task = new Task<int>(() => SumOfAllNumber(arrNum)); . If you can see, here we have declared as Task<int> which means the return type we are expecting is of type int .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
using System; using System.Threading.Tasks; namespace TaskInCshap { class Program { static void Main(string[] args) { int[] arrNum = new int[] { 13, 14, 25, 30, 56, 11, 20, 29 }; //Create a Task<TResult> instance, return type is int Task<int> task = new Task<int>(() => SumOfAllNumber(arrNum)); task.Start(); //Get the return value from Task int sum = task.Result; Console.WriteLine("Sum of all numbers in array : {0}", sum); Console.WriteLine("In Main Method, Finished work on thread Id: {0}", System.Threading.Thread.CurrentThread.ManagedThreadId); } private static Int32 SumOfAllNumber(int[] arrNum) { int sum = 0; for (int i = 0; i < arrNum.Length; i++) sum = sum + arrNum[i]; Console.WriteLine("In Child Method, Finished work on thread Id : {0}", System.Threading.Thread.CurrentThread.ManagedThreadId); return sum; } } } |
When we run above example then will get below output.
In the above console window, we can see that both Main method and Task executed on different thread. However since we are using Task.Result property in the Main method to read the return value from the Task. So, that’s why it blocked the Main method until it finished execution.
Example : Return value from a Task using Task.Run() :
Above example can be re written using Task.Run() method along with Lambda and named method expression. In below we have created a lambda expression and returns sum of the items present in the array.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
using System; using System.Threading.Tasks; namespace TaskInCshap { class Program { static void Main(string[] args) { int[] arrNum = new int[] { 13, 14, 25, 30, 56, 11, 20, 29 }; //Create a Task<TResult> instance, return type is int Task<int> task = Task<int>.Run(() => { int tempSum = 0; for (int i = 0; i < arrNum.Length; i++) tempSum = tempSum + arrNum[i]; return tempSum; }); //Get the return value from Task int sum = task.Result; Console.WriteLine("Sum of all numbers in array : {0}", sum); Console.WriteLine("In Main Method, Finished work on thread Id: {0}", System.Threading.Thread.CurrentThread.ManagedThreadId); } } } |
When we run above program, we will get output as below.
In the above console window, you can see that both Main method and Task executed on different thread. the Main thread was blocked until the child thread finished the Task execution.
Thanks for your time 🙂