Sunday, February 8, 2015

Asynchronous Methods Ex: 2


namespace AsynchronousMethods_Take2
{

    //a class object
    class Account
    {
        public int AccountNumber { get; set; }
        public decimal Balance { get; set; }
    }
}
//========================================================
using System.Windows.Forms;

namespace AsynchronousMethods_Take2
{
    public partial class Form1 : Form
    {
        Random rand = new Random();
        List<Account> accounts = new List<Account>();
        private void InitializeAccounts()
        {
            for (int i = 1; i <= 1000; i++)
            {
                int accountnumber = rand.Next(100000, 2000000000);
                decimal balance = rand.Next(100, 100000);
                accounts.Add(new Account
                {
                    AccountNumber = accountnumber,
                    Balance = balance
                });
            }
        }
        public Form1()
        {
            InitializeComponent();
            InitializeAccounts();
        }
        //method that adds up all the balances
        //this method to run asynchronously
        private void ComputeTotalBalances()
        {
            decimal sum = 0;
            foreach (Account a in accounts)
            {
                sum += a.Balance;
                System.Threading.Thread.Sleep(5);//to simulate long operation
            }
            //display the value
            string s = sum.ToString("c");
            SetText(s, richTextBox1);
        }

        private void btnAsynchronousCalls_Click(object sender, EventArgs e)
        {
            //run the ComputeTotalBalances method asynchronously
            //through delegates. You need a delegate with same signature as
            //the asynchronous method
            //you can define your own delegate type or use a predefined .net
            //delegate: Action

            //1. Create a delegate object that reference the asynchronous method
            Action action1 = ComputeTotalBalances;
            //2. Because this method returns no value, no callback is necessary
            //Call the BeginInvoke method of the delegate object
            action1.BeginInvoke(null, null);
        }

        //Resolving cross-threading exceptions
        //1. define a delegate with same signature as the crosss-threading handling
        // method (the SetText method)
        private delegate void RichTextBoxHandler(string s, RichTextBox rtb);
        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
                rtb.ScrollToCaret();
            }
        }

        private void btnRandomValues_Click(object sender, EventArgs e)
        {
            //synchronous method=>runs in the main thread
            int num = rand.Next();
            richTextBox2.AppendText(num.ToString()+ "\n");
            richTextBox2.ScrollToCaret();
        }

        //==============Asynchronous call with callback================
        //used for methods that return a value

        //run this method asynchronously
        private decimal GetAverageBalance()
        {
            decimal sum = 0;
            foreach (Account a in accounts)
            {
                sum += a.Balance;
                System.Threading.Thread.Sleep(3); //simulate a long process
            }
            return sum / accounts.Count;
        }

        private void btnGetAverageBxlance_Click(object sender, EventArgs e)
        {
            //goal:Call the GetAverageBalance asynchronously
            //since the method returns a value, you need to set up its callback method
            //the callback method MUST have the same signature as AsyncCallback delegate
            //So you need to create an ASyncCallback delegate and pass it to the BeginInvoke

            //run the GetAverageBalance asynchronously
            Func<decimal> function = GetAverageBalance;
                    //create an ASyncCallback delegate
            AsyncCallback callback = AverageBalanceCallback;

            function.BeginInvoke(callback, function);
           //the callback method need the reference function to call EndInvoke

        }
        //define your callback method that will receive the return value from the GetAverageBalance
        //MUST have the same signature as ASyncCallback delegate
        private void AverageBalanceCallback(IAsyncResult ar)
        {
            //retreive the function delegate
            Func<decimal> function = (Func<decimal>)ar.AsyncState;
            //use it to get the return value
            decimal average = function.EndInvoke(ar);
            string s = "Average accounts balances : " + average.ToString("c");
            SetText(s, richTextBox1);
        }
        //-------------------------------------------------------------------------
        //Lab Assignment: AsynchronousCalls --Due Friday 2-6
        //Create New Project
        //define a method Fibonacci that takes a value and returns a value. you could choose int, uint, long,ulong
        //or even double. Just make sure that you pass to it only integers
        private ulong Fibonacci(ulong num)
        {
            if (num == 0) return 0;
            if (num == 1) return 1;
            return Fibonacci(num - 1) + Fibonacci(num - 2);
        }
        //run the fibonacci series method asynchronously
        //be aware for num > 45 or 50 it may takes over a minute to run, depending on 
        //computer speed.
        //Add a button that reads a value from user and displays its fibonacci value
        //Add a second button that sequence (for loop) thru a list of input values 1 to 45
        //and display the fibonacci of each value.
        //the display should look like  Fib(inputvalue) = value (on each line) in a richTextbox
    }
}

No comments:

Post a Comment