Sunday, February 8, 2015

Intro to Asynchronous Methods


using System.Windows.Forms;



namespace IntroToAsynchronouseMethods
{
    public partial class Form1 : Form
    {
        Random rand = new Random();

        public Form1()
        {
            InitializeComponent();
        }

        private void btnRunSync_Click(object sender, EventArgs e)
        {
            //Calling both methods synchronously
            //both methods run in the main thread (UIthread).
            //the main thread can only run one after another
            DisplayOddRandomNumbers();
            DisplayEvenRandomNumbers();
        }

        private void btnRunAsynchronous_Click(object sender, EventArgs e)
        {
            //Step 1: Create a type of delegate
            //Need a delegate type with same signature as DisplayOddRandomMethod
            //Since .Net defines an Action delegate
            //public delegate void Action() that has the same signature as the method
            //you can use it.

            //Step 2.
            //Once a delegate type is defined or determined
            //create a delegate object and reference it to the method you want to run asynchronously

            Action oddAction = DisplayOddRandomNumbers;

            //now apply the BeginInvoke method of the delegate
            oddAction.BeginInvoke(null, null);

            //run the second display asynchronously
            Action evenAction = DisplayEvenRandomNumbers;
            evenAction.BeginInvoke(null, null);

            //Run the 3rd display method asynchronously
            //you need to pass an integer value to it thru the BeginInvoke
            Action<int> divBy3Action = DisplayDivisibleBy3;
            //we want 1500 values that are divisible by 3
            divBy3Action.BeginInvoke(1500, null, null);
        }

        //define 2 methods 
        private void DisplayOddRandomNumbers()
        {
           //Display 1,000 odd random
            int counter = 0;
            do
            {
                int num = rand.Next();
                if (num % 2 != 0)
                {
                    //richTextBox1.AppendText(counter + "    " + num + "\n");
                    SetText(counter + "  " + num, richTextBox1);
                   
                    //scroll down automaically
                    //rtb.ScrollToCaret();
                    counter++;
                }
            } while (counter < 1000);
        }

        private void DisplayEvenRandomNumbers()
        {
            //Display 1,000 odd random
            int counter = 0;
            do
            {
                int num = rand.Next();
                if (num % 2 == 0)
                {
                   // richTextBox2.AppendText(counter + "    " + num + "\n");
                    SetText(counter + "  " + num, richTextBox2);
                    //scroll down automaically
                    //rtb.ScrollToCaret();
                    counter++;
                }
            } while (counter < 1000);
        }
       
        //Define a 3rd method to run asynchronously
        //but this time this method takes one or more parameters
        private void DisplayDivisibleBy3(int maxCount)
        {
            //Display 1,000 odd random
            int counter = 0;
            do
            {
                int num = rand.Next();
                if (num % 3 == 0)
                {
                    // richTextBox2.AppendText(counter + "    " + num + "\n");
                    SetText(counter + "  " + num, richTextBox3);
                    //scroll down automaically
                    //rtb.ScrollToCaret();
                    counter++;
                }
            } while (counter < maxCount);
        }

        //Define a delegate with same signature as the cross-threading 
        //handling method (the SetText method)
        private delegate void RichTextBoxHandler(string s, RichTextBox rtb);

        //method to allow other threads to access the UI RichTextBox
        //this method should accept the string that you want to display in the UI
        private void SetText(string s, RichTextBox rtb)
        {
            if (rtb.InvokeRequired)
            {
                //create a delegate object
                RichTextBoxHandler handler = SetText;
                Invoke(handler, s, rtb);
            }
            else
            {
                rtb.AppendText(s + "\n");
                //scroll down automaically
                rtb.ScrollToCaret();
            }
        }

        //=======Asynchronous method that return a value===============
        private void btnAsyncMethodReturnValue_Click(object sender, EventArgs e)
        {
            //To get a return value from an asynchronous method 
            //you need to define a callback method. This callback method gets called when
            //the thread or that asynchronous method terminates. 
            //The return value can be retrieved from the callback method.

            //The callback method must have the same signature as AsyncCallback delegate

            //Create a delegate object for asynchronous method
            //use the Func<> delegate because the method returns value.
            Func<double> function = GetAvgOfOddRandomValues;

            //Create an AsyncCallack delegate to reference the method that gets called
            AsyncCallback callback = CallbackOfGetAvgOfRadomValues;
            //When the asynchronous completes. The callbcak method has the return value
            function.BeginInvoke(callback, function);
        }

        //define a callback method for the asynchronous GetAvgOfRandomValues
        private void CallbackOfGetAvgOfRadomValues(IAsyncResult ar)
        {
            //you need to retrive the return value
            //you need to use the SAME delegate object used to call the BeginInvoke.
           
            //get the function object passed as the last parameter in the BeginInvoke
            Func<double> function = (Func<double>)ar.AsyncState;
            //Get the return value from the asynchronous method
            double avg = function.EndInvoke(ar);
            SetText("average = " + avg, richTextBox4);
        }

        //method to run asynchronously. This method returns a value
        private double GetAvgOfOddRandomValues()
        {
            int counter = 0;
            double sum = 0;
            do
            {
                int num = rand.Next();
                if (num % 2 != 0)
                {
                    sum += num;
                    counter++;
                }
            } while (counter < 5000000);
            return sum/ counter;
        }
    }
}

//To read more links: 
//https://msdn.microsoft.com/en-us/library/2e08f6yc(v=vs.110).aspx
//https://msdn.microsoft.com/en-us/library/system.action(v=vs.110).aspx
//http://www.c-sharpcorner.com/UploadFile/835123/cross-thread-operations-in-C-Sharp/
//https://msdn.microsoft.com/en-us/library/hh191443.aspx
//http://www.csharp-examples.net/create-asynchronous-method/

//Lab Assignment: Due Wednesday 2-4; //New Project 
//Define a method that takes no parameters and returns a double 
//The method is to run asynchronously and computes the sum of Log of all the
//random values [ sum += Math.log(num)] generated. (generate few millions)
//Get and display the result thru its callback method
//====================================================
//Define a method that takes 2 integer values
//Add all the values between the 2 parameters incrementing by 0.01
//run the method asynchronously
//the method is to return the average value
//get and display its return value from the callback

No comments:

Post a Comment