Sunday, August 7, 2016

4. Exception handling in Async method



We can put try ..catch block in Async method to handle exception, we can put await statement inside of try..catch block or can use try ..catch in child method like...

  

       public static void Main()
        {
            Console.WriteLine("Calling Async method...");
            Task<double> result = DivideAsync(9, 0);
            Console.WriteLine("Division Result=" + result.Result);
         }

        public async static Task<double> DivideAsync(int a, int b)
        {
           Double result= await Task.Run<double>(()=>Divide(a,b));
           return result;
        }
        public static double Divide(int a, int b)
        {
            double r = 0;
            try
            {
                Thread.Sleep(5000);
                r = a / b;
            }
            catch (Exception ex)
            {
                //Log exception or show it to user
                MessageBox.Show(ex.Message);
            }
            return r;

        }

How to pass exception form child thread to parent thread


We can pass exception from child thread to parent thread with the help of delegate. we have to pass delegate in thread method and we will invoke delegate when any error occurred in child thread.
parent thread subscribes delegate so corresponding method will be invoked by delegate from child thread.
see below example:

using System.Threading.Tasks;
using System.Windows.Forms;
namespace GuruCSharpConsole.Threads
{
    public delegate void ErrorHandler(string errorMessage);
 //instead of string as input param we can also use Exception type as input param in delegate to get complete //exception details.
 
    class PassExceptionToMainThread
    {
       public static ErrorHandler errorHandler;

        public static void Main()
        {
            errorHandler += new ErrorHandler(ShowErrorMessage);

            for (int i = 0; i < 50; i++)
            {
                Thread t = new Thread(() => { DivideByZero(5, 0, errorHandler); }); //Passing delegate to each thread.
                t.Start();
             
            }
            Console.Read();
        }

        public static void DivideByZero(int a, int b,ErrorHandler eHandler)
        {
            try
            {
                double r = a / b;
                Console.WriteLine(" Result from thread {0} ={1}", Thread.CurrentThread.ManagedThreadId, r);
            }
            catch (Exception ex)
            {
                if (eHandler != null)
                {
                    eHandler("Thread=" + Thread.CurrentThread.ManagedThreadId + ex.Message);
                }
            }
        }

        public static void ShowErrorMessage(string err)
        {
            MessageBox.Show(err);
        }
    }
}

in the above example I am using System.Windows.Forms namespace to use "MessageBox" in console application otherwise it's not needed. 

Saturday, August 6, 2016

2. Asynchronous programming using Async and Await


Please read "Asynchronous programming using Async and Await" before reading it.

Asynchronous method with multiple await :

class AsyncAwaitTest
    {
        public static void Main()
        {            
            Task t =  M1Wrapper();
            //Other Operation ....
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("Main i=" + i);
            }
            Console.ReadKey();
        }
        public async static Task M1Wrapper()
        {
            Task t1 = Task.Run(() => M1());
            Task t2 = Task.Run(() => M2());
            Task t3 = Task.Run(() => M3());
            await t1;
            await t2;
            await t3;
        }

        public static void M1()
        {
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(" Method M1: i=" + i);
            }
        }
        public static void M2()
        {            
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(" Method M2: i=" + i);
            }
        }
        public static void M3()
        {           
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(" Method M3: i=" + i);
            }
        }


    }

Output:


3.Asynchronous programming using Async and Await (Dependent Async Operation)


Dependent Asynchronous operation example:

In below example we have 3 tasks t1,t2 and t3. Task  t1's result will be used in t2 and t2's result will be used in t3.
Operation t1 will take more time to complete as I have used Thread.Sleep(10000) so it will take 10 second to complete it's operation.


class DependentAwait
    {
        public static void Main()
        {          
            Task t =  M1Wrapper();

            Console.WriteLine("Final Result=" + t.Result);
            Console.ReadKey();
        }
        public async static Task M1Wrapper()
        {
            Task t1 = Task.Run(() => { Thread.Sleep(10000);  return M1(4, 5); });
            await t1;
            Task t2 = Task.Run(() => M1(t1.Result,5));
            await t2;
            Task t3 = Task.Run(() => M1(t2.Result,5));
            return await t3;
       
        }
        public static int M1(int a,int b)
        {
            return a + b;
        }
     
    }

Output : Result of above program would be 19.

1. Asynchronous programming using Async and Await


Asynchronous programming makes it possible to run multiple operation concurrently, In other words Asynchronously.
Dot Net framework 4.0 supports Task based asynchronous programming model.
We will see by example how to implement asynchronous programming using async and await keyword.
suppose we have a long running operation named M1(), like:

      public static void M1()
       {
           for (int i = 0; i < 10000; i++)
           {
               Console.WriteLine(" From M1, i=" + i);
           }
       }
Above mentioned method is our actual operation which we want to run asynchronously. in this operation I used static keyword because I want to use this operation in Main method which is static.

Now we will create a new method  M1Wrapper() which will use async and await keyword, this new method will call M1() method and uses async,await and Task keywords like:

        public async static Task M1Wrapper()
        {
            await Task.Run(() => M1());
        }

To implement M1Wrapper() you need to remember :

  • Name of method : just for understanding purpose I am using method name as M1Wrapper but as a standard practice name should be M1Async to represent asynchronous operation.
  • you should use await followed by Task.Run method to run operation asynchronously.I am using non generic version of Run because it's (M1) return type is void. 
  • In method signature I have used async keyword which is necessary to make operation asynchronous.
  • Note that I am using Task as return type but it's not necessary if your operation returns void, but I used Task because I want to wait until this asynchronous operation will complete.it's possible by calling Task.Wait() method.(see complete code below to understand this concept in detail.) 
  • In case your method returns any other type then you have to use Task.Run  where T is return type.
  • You can use any no of input parameter in async method but remember that you can not use ref and out parameter in asynchronous method. 
  • Instead of creating a method M1 and then async wrapper method (M1Wrapper), you can put M1's code inside of Task.Run() method in-place of M1(). To make things easier to understand I created separate methods.
  • An async method that has a void return type can’t be awaited, and the caller of a void-returning method can't catch any exceptions that the method throws.

 Complete Code:

         public static void Main()
        {            
            Task t = M1Wrapper();

            //Other Operation ....

            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("Main i=" + i);
            }
            t.Wait();
            Console.ReadKey();
        }
        public async static Task M1Wrapper()
        {
            await Task.Run(() => M1());
        }

        public static void M1()
        {
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(" From method M1: i=" + i);
            }
        }

Result :









C# Record type: Something to remember while using record types

  Record in c# provide a concise and expressive way to create immutable data types, record is a keyword in c#, we can use this keyword with ...