Робота з асинхронними викликами

Асинхронні виклики

 

Перший випадок :

Потрібно розрахувати 2+2 (метод займає 5 секунд) та прокрутити прогресс бар (метод займає 5 секунд) .

 

Робимо це послідовно та дивимось на наслідок:

 

використані  методи

 

        private double Calc2x2(double x, double y)

        {

            // засинаємо на 5 секунд

            Thread.CurrentThread.Sleep(5000);

            // повертаємо результат

            return x * y;

        }

 

        private void MoveProgressbar()

        {

            for (int i = 0; i < 100; i++)

            {

                Thread.Sleep(50);

                progressBar1.Value = i;

            }

        }

 

Запускаємо синхронно

 

        private void button1_Click(object sender, EventArgs e)

        {

            double c = this.Calc2x2(3,4);

            label1.Text = c.ToString();

            this.MoveProgressbar();

        }

 

здається, що на певний час програма «зависає». Зробимо це з методом очікування:

 

        delegate double CalcDelegate(double x, double y);

        private void button2_Click(object sender, EventArgs e)

        {

            CalcDelegate fun = new CalcDelegate(Calc2x2);

            // starting ansyc execution

            IAsyncResult res =  fun.BeginInvoke(3, 4, null, null);

 

           

            this.MoveProgressbar();

 

            // ending ansyc execution

            double c = fun.EndInvoke(res);

            label1.Text = c.ToString();

        }

 

Теж здається, що програма підвисає, проте не на 10, а на 5 секунд. Чому? Тому що виконання зміни прогрес-бару блокує реакцію на дії користувача. Зробимо так, запустим обидва методи асинхронно, а за таймером будемо перевіряти готовність першого виклику

 

        delegate double CalcDelegate(double x, double y);

        delegate void MoveSth();

        private void button3_Click(object sender, EventArgs e)

        {

            fun = new CalcDelegate(Calc2x2);

            // starting ansyc execution

            myres = fun.BeginInvoke(3, 4, null, null);

 

            MoveSth fun2 = new MoveSth(MoveProgressbar);

            fun2.BeginInvoke(null, null);

                    

 

        }

 

        private void timer1_Tick(object sender, EventArgs e)

        {

            if ((myres != null) && (myres.IsCompleted))

            {

                // stop the timer

                timer1.Enabled = false;

                               

                // ending ansyc execution

                double c = fun.EndInvoke(myres);

                label1.Text = c.ToString();

 

                myres = null;

            }

 

        }

 

Висновки:

  1. Програма не зависає
  2. Результат  множення ми у більшості випадків отримуємо, ще до завершення прогрес-бару.