АкушерствоАнатомияАнестезиологияВакцинопрофилактикаВалеологияВетеринарияГигиенаЗаболеванияИммунологияКардиологияНеврологияНефрологияОнкологияОториноларингологияОфтальмологияПаразитологияПедиатрияПервая помощьПсихиатрияПульмонологияРеанимацияРевматологияСтоматологияТерапияТоксикологияТравматологияУрологияФармакологияФармацевтикаФизиотерапияФтизиатрияХирургияЭндокринологияЭпидемиология

Пример создания многозадачного приложения с помощью системы программирования Borland Delphi

Прочитайте:
  1. HLA- DR, DQ, DP. В этой же зоне находятся и другие гены: например, DN, DO, продукты которых пока не известны.
  2. I. Противоположные философские системы
  3. II. Клетки иммунной системы
  4. III. После этого раненую конечность лучше всего зафиксировать, например, подвесив на косынке или при помощи шин, что является третьим принципом оказания помощи при ранениях.
  5. IV. Анатомия органов сердечно-сосудистой системы
  6. IV. Порядок проведения и примерное распределение времени
  7. IV. Реакция эндокринной системы на гипогликемию
  8. V. Органы лимфатической системы, иммунной системы
  9. VI. Анатомия центральной нервной системы
  10. VII. Анатомия периферической нервной системы

Рассмотрим пример использования механизмов, специально созданных для ор­ганизации взаимного исключения, которые имеются в системе программирова­ния Borland Delphi 3.0. Эта система программирования, будучи ориентирован­ной на создание приложений в многозадачной операционной системе Microsoft Windows 9x, содержит в себе стандартные классы, позволяющие без особых уси­лий использовать многопоточные возможности этих ОС. Воспользуемся стан­дартным классом TThread. Объект, создаваемый на основе этого класса, можно охарактеризовать следующими теперь уже очевидными для нас свойствами:

Q каждый тред имеет свою, при необходимости уникальную, исполняемую часть;

Q каждый тред для своего исполнения требует отдельного процессорного вре­мени, то есть диспетчер задач принимает во внимание только приоритет треда;

Q диспетчеризация выполнения тредов осуществляется операционной системой и не требует вмешательства программиста;

Q несколько тредов, принадлежащих одному процессу, могут использовать один и тот же ресурс (например, глобальную переменную). Как нам известно, тре­ды могут обращаться к полям другого треда из того же вычислительного про­цесса. При этом программисту необходимо самостоятельно ограничивать дос­туп к этому ресурсу во избежание известных проблем.

Итак, пусть необходимо создать многопоточное приложение, схема взаимодейст­вия отдельных потоков в котором (в рамках единого вычислительного процесса) приведена на рис. 6.6.



Так, согласно этому рисунку, процесс А после своего завершения запускает зада­чи D, С и Е. Считаем, что задачи В, D и С завершаются примерно в одинаковое время. По крайней мере, нам не известно, какой из потоков должен быть первым, а какой — последним. Однако по условиям задачи пусть поток F будет запус­каться тем из перечисленных тредов, который завершается первым, но только после того, как завершатся два оставшихся треда, приходящие в «точку синхро­низации». Наконец, пусть задача G запускается последним закончившим работу потоком Е или F.

Все указанные задачи создадим как потомки объекта TThread. Тексты всех про­граммных модулей приведены в приложении А. Поскольку, согласно условию, действия, выполняемые задачами, для нас не имеют значения, представим ис­полняемую часть простейшим циклом с соответствующей задержкой. Для нагляд­ности внутри цикла можно организовать вывод текущего состояния выполнения задачи в процентах на «строке состояния», для чего используем компонент TGauge. Благодаря тому, что все семь тредов похожи (используют одни и те же методы) и отличаются только в части принятия решения о синхронизации, опишем орга­низацию базового объекта-треда.

Базовый объект (TTreadProgress) является потомком объекта TTread. При этом он имеет следующие поля:

Q имя треда;

Q строка состояния треда;

Q «длина» треда (время его работы в отсутствие конкурентов);

Q текущее состояние треда;

Q признак завершения треда;

Q имя запустившего треда;

О строка для вывода сообщений в компонент ТМето.

В базовом объекте объявлены следующие процедуры:

Q исполняемая часть;

Q завершающая часть;

Q процедура прорисовки строки состояния;

Q процедура вывода сообщения;

О конструктор объекта.


Все треды (от А до G) являются потомками этого объекта и перекрывают един­ственный метод — процедуру завершения процесса. В исполняемой части задачи после завершения цикла задержки, имитирующего выполнение полезной рабо­ты, устанавливается признак завершения и вызывается процедура завершения задачи, которая и выполняет соответствующие действия.

Общую схему работы программы, реализующей задание, можно описать следую­щим образом. Все задачи инициализируются соответствующей процедурой од­новременно, но в режиме ожидания запуска. В качестве параметров инициализа­ции в создаваемый поток передаются его имя, длительность и имя запускающего объекта (если оно известно заранее). Сразу после инициализации запускаются задачи А и В. Обе задачи сигнализируют об этом соответствующим сообщением. После своего завершения поток А запускает задачи (потоки) С, D и Е. Далее все идет в соответствии с заданной блок-схемой. Задача, запускающая другую зада­чу, передает ей свое имя, обращаясь непосредственно к полю этого объекта. Ин­формацию о том, завершился тот или иной поток, можно получить, обратившись к соответствующему полю — признаку завершения задачи.

Естественно, что при подобной организации доступа к полям тредов вероятно возникновение разного рода критических ситуаций. Напомним, основная причи­на их возникновения заключена в том, что несколько задач (в нашем случае — потоков) реально имеют возможность обращения к общим ресурсам практиче­ски одновременно, то есть с таким интервалом времени, за который этот ресурс не успеет изменить свое состояние. В результате задачи могут получать некор­ректные значения, о чем мы уже немало говорили.

Каждый процесс имеет связь с так называемыми VCL-объектами — видимыми компонентами. В данном случае такими являются строка состояния TGauge и поле сообщений ТМето. Для того чтобы в процессе работы нескольких парал­лельно выполняющихся задач не возникало критических ситуаций с выводом информации на эти видимые на экране объекты, к ним необходимо обеспечить синхронизированный доступ. Это довольно легко достигается с помощью стан­дартного для объекта TThread метода Synchronize. Метод имеет в качестве пара­метра имя процедуры, в которой производится вывод на VCL-объекты. При этом сама эта процедура нигде в программе не должна вызываться напрямую без ис­пользования метода Synchronize. В нашей программе такими процедурами явля­ются прорисовка строки состояния (Do Visual Progress) и вывод текстового сообщения (WriteToMemo). Подобное использование метода Synchronize обес­печивает корректную работу нескольких параллельных процессов с VCL-объек­тами.

Однако метод Synchronize не помогает в случае совместного доступа к другим общим ресурсам. Поэтому необходимо применять другие средства для организа­ции взаимного исключения. Главная цель этих средств заключается в обеспече­нии монопольного доступа для каждой задачи к общим ресурсам, то есть пока один поток не закончил обращение к подобному ресурсу, другой не имеет право этот ресурс использовать.

В системе программирования Delphi для этой цели имеется довольно-таки про­стой в использовании и достаточно эффективный метод критической секции с помощью объекта TCriticalSection. Этот метод заключается в следующем:


Q участок кода каждого потока, в котором производится обращение к общему ресурсу, заключается в «скобки» критической секции — используются мето­ды Enter и Leave;

Q если какой-либо тред уже находится внутри критической секции, то другой поток, который дошел до «открывающей скобки» Enter, не имеет права вхо­дить в критическую секцию до тех пор, пока первый поток находится в ней. Когда первый тред выйдет из критической секции, второй сможет войти в нее и, в свою очередь, обратиться к критическому ресурсу.

Очевидно, что такой метод надежно обеспечивает задачам монопольный доступ к общим (критическим) ресурсам.

Метод критической секции имеет ряд преимуществ перед его аналогами. Так, например, использование семафоров (Semaphore) сложнее в реализации. Другой метод взаимных исключений — mutex — в целом похож на метод критической секции, но он требует больше системных ресурсов и имеет свое время тайм-аута, по истечении которого ожидающий процесс может все-таки войти в защищен­ный блок, в то время как в критической секции подобного механизма нет.

Текст всей программы с необходимыми комментариями приведен в приложении А.


Дата добавления: 2015-01-18 | Просмотры: 671 | Нарушение авторских прав



1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |



При использовании материала ссылка на сайт medlec.org обязательна! (0.004 сек.)