Тема 2.9 Создание многопоточных приложений
1. Понятие потоков и процессов.
2. Средства синхронизации потоков.
3. Создание модулей-потоков в Delphi.
4. Свойства и методы потоков.
Понятие потоков и процессов
Визуальная среда программирования Delphi предоставляет прекрасные возможности для разработки приложений, и использует при этом все возможности операционной системы. Одна из важных возможностей, которую поддерживает среда разработки Delphi - это создание приложений, состоящих более чем из одного потока.
Потоки позволяют в рамках одной программы решать несколько различных задач одновременно.
Потоки - это объекты, получающие процессорное время. Время процессора выделяется специальными порциями, называемыми квантами. Квант называется интервал времени, имеющийся в распоряжении потока до тех пор, пока время не будет передано в распоряжение другого потока.
Кванты выделяются не программам и процессам, а порожденным этими процессами потокам. Каждый процесс состоит минимум из одного потока. Сегодня все современные операционные системы позволяют запускать в рамках одного процесса несколько различных потоков.
Преимущество использования потоков:
1. Разделение большой задачи на несколько подзадач, что повышает переносимость кода программы и возможности его многократного использования.
2. Дополнительные возможности управления приложением за счет управления приоритетами потоков.
|
|
3. Возможность снять проблему возрастания "нагрузки" на приложение, увеличением количества потоков.
Ассиметричные потоки - решающие различные задачи и не разделяющие совместные ресурсы. Необходимость в ассиметричных потоках возникает в следующих случаях:
- когда в программе необходимы длительные вычисления, при этом сохраняя нормальную реакцию на ввод;
- при необходимости обработки асинхронного ввода/вывода с использованием различных устройств;
- если необходимо создать несколько окон и одновременно обрабатывать ввод в них данных.
Существует две проблемы, с которыми можно столкнуться при работе с потоками - это тупики и гонки.
Тупики имеют место, когда один поток ожидает ресурс, который в данный момент принадлежит другому потоку. Например, поток 1 захватить ресурс А, и для продолжении работы, ждет возможности захватить ресурс В. В то же время второй поток - Поток 2 захватывает ресурс В и ждет возможности захватить ресурс А. В результате этого сценария заблокируется оба потока; ни один из них не будет исполняться. Такими ресурсами могут выступать любые совместно используемые объекты системы - файлы, область памяти, внешние устройства.
|
|
Гонки возникают в ситуации, когда два или более потока пытаются получить доступ к общему ресурсу и изменить его состояние. Пусть Поток 1 получит доступ к ресурсу и изменил его в соответствии со своими интересами; затем активизировался второй поток Поток 2 и обратился к этому же ресурсу до завершения Потока 1. Поток 1 полагает, что ресурс остался в том же состоянии, в каком был до переключения. В зависимости от того, когда именно был изменен ресурс, результаты могут меняться - иногда программа будет выполняться нормально, иногда нет.
Для разрешения ситуаций гонок и тупиков можно использовать некоторые приемы.
Средства синхронизации потоков
Возможными вариантами решения проблемами является 4 объекта, которые разработаны специально для синхронизации. Это такие объекты как событие, взаимное исключение, семофор и таймер.
Помимо этого можно организовать ожидание и других объектов, дескриптор которых используется в основном для иных целей, но может применяться и для ожидания. К ним относятся: процесс, поток, оповещение об изменении в файлой системе и консольный ввод.
Событие - простейший выбор для задач синхронизации. Класс TEvent (событие) имеет два важных метода: setEvent - перевод объекта в активное состояние и ResetEvent- перевод в пассивное состояние.
|
|
Конструктор события имеет следующий вид:
constructor Create (Event Attributes: PSecurity Attributes; ManualReset, InitialState: Booiean; const Name: string);
где параметр initialstate- начальное состояние объекта,
ManualReset- способ его перевода в пассивное состояние. Если этот параметр равен True, событие должно быть переведено в пассивное состояние вручную. Иначе событие сбрасывается по мере того, как стартует хоть один поток, ждавший данный объект.
Взаимное исключение позволяет владеть ресурсом в данное время одному из потоков. Класс, инкапсулирующий взаимное исключение TMutex.
Конструктор: constructor Create(const Name: string); задает имя создаваемого объекта. Первоначально объект не принадлежит никому.
Семафор подобен взаимному исключению. Разница между ними состоит в том, что семафор может управлять количеством потоков, имеющим к нему доступ. Семафор устанавливается на максимальное число потоков, к которым разрешен доступ. При достижении количества потоков этого максимума, последующие потоки будут приостановлены.
В Delphi можно использовать также объект типа критическая секция.
|
|
Критические секции подобны взаимным исключениям, однако ,между ними существуют два главных отличия:
- взаимные исключения в отличие от критических секций могут быть
совместно использованы потоками в различных процессах;
- если критическая секция принадлежит другому потоку, ожидающий
поток блокируется вплоть до освобождения критической секции. В
отличие от этого, взаимное исключение разрешает продолжение по
истечении тайм-аута.
Критические секции и взаимные исключения очень схожи. На первый взгляд, выигрыш от использования критической секции вместо взаимного исключения не очевиден. Критические секции более эффективны , чем взаимные исключения, т.к. используют меньше системных ресурсов. Критическая секция всегда ждет столько времени, сколько потребуется; взаимные исключения же могут быть установлены на определенный интервал времени, по истечении которого выполнение продолжается.
Создание модулей потоков в Delphi
Для создания дополнительного потока в программах Delphi предназначен специальный модуль - Thread Object. Для его создания используется команда File -> New. При выборе этого модуля Delphi запрашивает имя класса, который будет дочерним для основополагающего класса TThread. Необходимость наследования связана с тем, что класс TThread содержит абстрактный метод Execute, который обязан перекрываться в потомках.
Файл модуля-потока имеет следующую структуру:
unit Unit2;
interface
uses
Classes;
type
MyThread = class(TThread)
private
Private declarations
protected
procedure Execute; override;
end;
implementatoin
procedure MyThread. Execute;
begin
Place thread code here
end;
end.
Программирование потока имеет важное отличие от обычной программы - поток не может использовать методы и свойства визуальных компонентов, которые приводят к изменению внешнего вида программы. Для этого поток обращается к специальному методу Synchronize, с помощью которого осуществляется синхронизация исполнения главного потока с дополнительным. Единственным параметром обращения к этому методу должно быть имя любой процедуры без параметров. Внутри такой процедуры допустимо обращение к методам и свойствам визуальных компонентов.
Свойства и методы потоков
1. Procedure Execute; virtual; abstract; - код, исполняемый в создаваемом потоке TThread.
2. property Terminated: Boolean; -это указание потоку завершиться с возможностью корректно освободить ресурсы.
3. Метод WaitFor предназначен для синхронизации и позволяет одному потоку дождаться момента, когда завершится другой поток.
4. Свойство Priority позволяет запросить и установить приоритет потоков. Допустимыми значениями приоритета для объектов TThread являются такие значения tridle, tpLowest, tpLower, tpNormai, tpHigher, tpHignest и tpTimeCritical.
5. procedure Synchronize (Method; TThreadMethod); Этот метод относится к секции protected, т.е. может быть вызван только из потомков TThread, Delphi предоставляет метод Synchronize для безопасного вызова методов VCL внутри потоков. Во избежание конфликтных ситуаций , метод Synchronize дает гарантию, что к каждому объекту VCL одновременно имеет доступ только один поток. Аргумент, передаваемый в метод Synchronize,- это имя метода, который производит обращение к VCL;вызов Synchronize с этим параметром -это то же, что и вызов самого метода.
6. procedure Suspend;
7. Вызов метода Suspend приостанавливает поток, сохраняя возможностью повторного запуска. Метод Suspend приостанавливает поток вне зависимости от кода, который исполняется потоком в данный момент; выполнение продолжается с точки останова.
8. Свойство Suspend позволяет программисту определить, не приостановлен ли поток.
Свойство ReturnValue позволяет узнать и установить значение, возвращаемое потоком его завершении.
Дата добавления: 2018-04-05; просмотров: 422; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!