Главная · Карта сайта · Поиск · Статьи · Компьютерные курсы · Обучающие программы · Открытые проекты · Веб-программирование · Создание интернет-сайта · Полезные ссылки · Глоссарий · Контакты · Декабрь 09 2016 20:22:17
Последнее опубликованное

Что такое Model-View-Controller
Pattern Model-View-Controller

Как создать свой веб-сайт
Как создать свой сайт в интернете

Разное
Статистика

Программирование на C#. Параллельные вычисления. Асинхронный вызов делегата


[Назад] [Следующая страница]

6.5. Асинхронный вызов делегата

Еще одним очень простым в реализации способом выполнить что-либо в параллельном по отношению к основным вычислениям потоке является асинхронный вызов делегата. Для этого группируем код, который предполагается исполнять параллельно в отдельный метод, объявляем соответствующий по сигнатуре делегат, и присваиваем экземпляру этого делегата ссылку на наш метод. Оказывается, у делегата уже есть все необходимое, чтобы выполнить асинхронный вызов переданного ему метода, вернуть управление основному потоку, и после того, как основной поток завершит то, для чего ему управление было передано, дождаться окончания выполнения параллельных вычислений.

Есть один нюанс: параллельные вычисления могут закончиться как позже основных, так и раньше. С первым случаем все понятно – мы дожидаемся их окончания вызовом метода EndEnvoke(). Во втором случае параллельный поток может сообщить о своем досрочном завершении посредством обратного вызова. В приведенном примере метод MyReport() вызывается параллельно. Методу BeginEnvoke() делегата, осуществляющего асинхронный вызов MyReport(), помимо параметра IterationsCount, передается указатель на метод MyReportCompleted(), который и будет вызван по окончанию “формирования отчета”. Важно учесть, что метод обратного вызова будет вызван в параллельном потоке, а значит нужно быть аккуратным при обновлении элементов пользовательского интерфейса и действовать по аналогии с предыдущим шагом: использовать свойство InvokeRequired и метод Invoke().

Пример работы обучающей программы
Пример работы программы с асинхронным вызовом делегата.

        //Пример 3. Асинхронный вызов делегата
        //Объявление делегата
        private delegate void MyReportDelegate(int _IterationsCount);

        //Вызов асинхронного делегата
        private void btnASDInvoke_Click(object sender, EventArgs e)
        {
            int _IterationsCount = Convert.ToInt32(numericUpDownWork.Value);
            //Начало обработки в параллельном потоке
            MyReportDelegate _invoke = MyReport;
            //В качестве параметра передается метод, который будет вызван по окончанию работы MyReport
            IAsyncResult _invokeResult = _invoke.BeginInvoke(_IterationsCount, MyReportCompleted, this);

            //'Обнуление' протокола
            this.ASDLog = string.Empty;
            //Параллельная MyReport обработка...
            for (int i = 0; i < _IterationsCount; i++)
            {
                this.ASDLog = this.ASDLog + "Другая работа... " 
                    + Math.Round((100 * (double)(i + 1) / _IterationsCount), 2).ToString() 
                    + "%" + Environment.NewLine;
                Thread.Sleep(10);
            }

            this.ASDLog = this.ASDLog + "Другая работа завершена." + Environment.NewLine;

            //Дожидаемся окончания обработки MyReport
            _invoke.EndInvoke(_invokeResult);

            //Вывод протокола обработки
            textBoxASDInvokeLog.Text = this.ASDLog + "Все работы завершены." + Environment.NewLine;
        }
        //Формирование отчета
        private void MyReport(int _IterationsCount)
        {
            for (int i = 0; i < _IterationsCount; i++)
            {
                this.ASDLog = this.ASDLog + "Формирование отчета... " 
                    + Math.Round((100 * (double)(i + 1) / _IterationsCount), 2).ToString() 
                    + "%" + Environment.NewLine;
                Thread.Sleep(10);
            }
        }
        //Завершение формирования отчета
        private void MyReportCompleted(object state)
        {
            textBoxASDInvokeLog.Text = textBoxASDInvokeLog.Text + "!";
            this.ASDLog = this.ASDLog + "Формирование отчета завершено." + Environment.NewLine;
        }

И еще один момент. Ниже приведен фрагмент кода, реализующий свойство ASDLog, доступ к которому необходимо разделять между потоками. Разделяемый ресурс, в первую очередь, необходимо оградить от одновременной корректировки несколькими потоками, а в предоставлении доступа на чтение нескольким потокам сразу нет ничего криминального. Но, если доступ на чтение вообще никак не ограничивать, то может случиться ситуация, когда во время изменения ресурса кто-то попытается его прочитать. Исход этой ситуации непредсказуем, и все зависит от природы ресурса. Экземпляры класса ReaderWriterLockSlim помогают решить задачу оптимизации потокобезопасного доступа к ресурсу: они позволяют его читать нескольким потокам сразу, но, если один из потоков получил доступ на редактирование, то все “читатели” на время редактирования блокируются.

        //Протокол обработки
        private string m_ASDLog = string.Empty;
        //Потокобезопасная блокировка, оптимизированная для чтения
        private ReaderWriterLockSlim m_ASDLogLock = new ReaderWriterLockSlim();

        //Свойство "Протокол обработки", использующее ReaderWriterLockSlim
        internal string ASDLog
        {
            get
            {
                m_ASDLogLock.EnterReadLock();

                try
                {
                    return m_ASDLog;
                }
                finally
                {
                    m_ASDLogLock.ExitReadLock();
                }
            }

            set
            {
                m_ASDLogLock.EnterWriteLock();

                try
                {
                    m_ASDLog = value;
                }
                finally
                {
                    m_ASDLogLock.ExitWriteLock();
                }
            }
        }


[Назад] [Следующая страница]

Компьютерные курсы и курсы программирования
Основы программирования

Курс для начинающих программистов на C# и VB.NET.

SQL 25™

Построение SQL запросов и работа с базой данных.

C# Quick Guide™

Программирование на C#. Краткое руководство.

RegEx

Применение регулярных выражений.

Plug-in архитектура

Примеры программной Plug-in архитектуры.

XML и его расширения

Язык разметки XML и его расширения с примерами.

HTML и разметка гипертекста

Языки HTML, XHTML и CSS с примерами разметки.

Основы веб-дизайна

Основы веб-дизайна: решения типовых задач верстки.

Программирование на PHP

Руководство по программированию на PHP для начинающих.

Справочные материалы

Шаблоны проектирования
Каталог шаблонов проектирования программных компонентов.

Рефакторинг кода
Каталог приемов рефакторинга программного кода.

Гость
Имя

Пароль



Забыли пароль?
Запросите новый здесь
.
Coding Craft. Все права защищены © 2011. Проект Инициативного Народного Фронта Образования - ИНФО-проект.