Главная    Почта    Новости    Каталог    Одноклассники    Погода    Работа    Игры     Рефераты     Карты
  
по Казнету new!
по каталогу
в рефератах

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

о  теле
должен содержаться код, который и представляет собой собственно поток.  Если
поток был создан  с  аргументом  CreateSuspended,  равным  FALSE,  то  метод
Execute вызывается сразу после создания потока; в противном случае  -  после
вызова метода Resume.
Если поток рассчитан на  однократное  выполнение  каких  либо  действий,  то
никакого специального кода  завершения  для  него  писать  не  нужно.  После
выполнения метода Execute  будет  вызван  деструктор,  который  сделает  все
необходимое.
Если же  в  потоке  будет  выполняться  бесконечный  цикл,  и  поток  должен
завершиться вместе с приложением, то условия  окончания  цикла  должны  быть
примерно такими:


rocedure tMyThread.Execute;

Begin

Repeat

// Код потока

Until CancelCondition or Terminated;

End;
Здесь CancelCondition - ваше личное условие завершения  потока,  а  свойство
Terminated говорит о  завершении  потока  извне  (скорее  всего,  завершился
породивший его процесс).
С завершением потока нужно быть  очень  внимательным:  если  он  зациклился,
зависнет все приложение.
Свойство Property ReturnValue: Integer;
Позволяет узнать код завершения потока. Эта величина полностью  определяется
пользователем.
Для создания своего потока следует найти в репозитории значок Thread  Object
(он находится на странице  New).  Двойной  щелчок  на  этом  значке  вызовет
диалоговое окно New Thread Object, в которое  следует  ввести  имя  будущего
класса-потомка tThread. Нажатие кнопки ОК вызовет генерацию  шаблона  нового
потока:


unit ThreadUnit;

interface

uses Classes;


type

tMyThread = class(TThread)

private

{ Private declarations }

protected

procedure Execute; override;

end;


implementation


{ Important: Methods and properties of objects in VCL can only be used in  a
method called using Synchronize, for example,


Synchronize(UpdateCaption);


and UpdateCaption could look like,


procedure tMyThread.UpdateCaption;

begin

Form1.Caption := 'Updated in a thread';

end; }


{ tMyThread }


procedure tMyThread.Execute;

begin

{ Place thread code here }

end;


end.
Средства синхронизации потоков
Главные  понятия  механизма  синхронизации  -  функции  ожидания  и  объекты
ожидания.  В  API  предусмотрен  ряд  функций,   позволяющих   приостановить
выполнение вызвавшего эту функцию потока вплоть до того момента,  как  будет
изменено состояние какого-нибудь  объекта,  называемого  объектом  ожидания.
(Под этим термином  понимается  не  объект  Delphi,  а  объект  операционной
системы.) К возможным  вариантам  относятся  четыре  объекта,  разработанных
специально для синхронизации:
1. Событие (event);
2. Взаимное исключение (mutex);
3. Семафор (semaphore);
4. Таймер (timer).
Кроме них, ждать можно и других объектов, дескриптор которых используется  в
основном для других целей, но  может  применяться  и  для  ожидания.  К  ним
относятся: процесс,  поток,  оповещение  об  изменении  в  файловой  системе
(change notification) и консольный ввод. Соответствующие классы находятся  в
модуле SYNCOBJS.PAS.
Событие
(класс tEvent) имеет два метода: SetEvent и ResetEvent,  переводящие  объект
в активное и пассивное состояние соответственно.  Конструктор  класса  имеет
вид:
Constructor   Create(EventAttributes:   pSecurityAttributes;    ManualReset,
InitialState:Boolean; const Name:string);
Здесь параметр EventAttributes определяет  права  доступа  к  событию  и,  в
большинстве случаев должен быть равен nil. Параметр InitialState  определяет
начальное состояние события. Параметр ManualReset - способ его сброса.  Если
этот параметр равен  TRUE,  то  событие  должно  быть  сброшено  вручную.  В
противном  случае  событие  сбрасывается  автоматически  после   того,   как
стартует хотя бы один дожидавшийся его поток.
Метод


type tWaitResult = (wrSignaled, wrTimeOut, wrAbandoned, wrError);

Function WaitFor(TimeOut:DWORD): tWaitResult;
Дает возможности ожидать активизации события в течение TimeOut  миллисекунд.
Метод возвращает wrSignaled в случае, если произошла активизация  события  и
wrTimeOut, если за время тайм-аута ничего не  произошло.  Если  нужно  ждать
бесконечно долго, следует установить параметр TimeOut в значение INFINITE.
Для синхронизации потоков  следует  вставить  вызов  WaitFor  в  необходимом
месте  кода  потока  (метода  Execute),  и  тогда  выполнение  потока  будет
приостановлено до момента активизации  события  (то  есть  когда  какой-либо
другой поток вызовет его метод SetEvent) или окончания тайм-аута.
Взаимные исключения
Объект типа взаимное исключение (класс tMutex, файл  IPCTHRD.PAS)  позволяет
только одному потоку в данный  момент  владеть  им.  Его  можно  сравнить  с
эстафетной палочкой. Первоначально, данный  объект  не  принадлежит  никому.
Метод


function Get(TimeOut:Integer):Boolean;
Производит попытку в течение TimeOut миллисекунд завладеть объектом (в  этом
случае метод возвращает TRUE). Если объект больше не нужен, следует  вызвать
метод


function Release: boolean;
Критическая секция
Критические секции (класс tCriticalSection) подобны взаимным исключениям  по
сути, но между ними существуют два главных отличия:
1.  Взаимные  исключения  могут  быть  совместно  использованы  потоками   в
различных процессах.
2. Если критическая  секция  принадлежит  другому  потоку,  ожидающий  поток
блокируется вплоть до освобождения критической секции. В отличие  от  этого,
взаимное исключение разрешает продолжение по истечении тайм-аута.
Критические секции эффективнее взаимных исключений, так как  они  используют
меньше системных ресурсов.
Работа с критическими секциями похожа на работу с взаимными исключениями.  В
многопотоковом  приложении  создается  и  инициализируется  общая  для  всех
потоков критическая секция.  Когда  один  из  потоков  достигает  критически
важного участка кода, он пытается захватить секцию вызовом метода Enter.


. . .

CriticalSection.Enter;

try

// критический участок кода

finally

CriticalSection.Leave;

end;

. . .
Когда другие потоки доходят до оператора захвата секции и обнаруживают,  что
она уже захвачена, они  приостанавливаются  вплоть  до  освобождения  секции
первым потоком  путем  вызова  метода  Leave.  Критические  секции  являются
системными объектами и подлежат обязательному освобождению (впрочем,  как  и
все другие рассматриваемые здесь объекты).
Процесс. Порождение дочернего процесса
Объект типа процесс может быть использован  для  того,  чтобы  приостановить
выполнение потока в случае, если  для  своего  продолжения  он  нуждается  в
завершении процесса. С практической точки зрения такая  ситуация  возникает,
когда в рамках вашего приложения возникает  необходимость  исполнить  другое
приложение.
Вместо  устаревшей  и  поддерживаемой  только  для   совместимости   функции
WinExec, гораздо правильнее пользоваться более мощной функцией:


function  CreateProcess(lpApplicationName:  pChar;   lpCommandLine:   pChar;
lpProcessAttributes, lpThreadAttributes: pSecurityAttribytes;

bInheritHandles:BOOL;

dwCreationFlags: DWORD;

lpEnviroment: Pointer;

lpCurrentDirectory:pChar;

const lpStartupInfo: tStartupInfo;

var lpProcessInformation: tProcessInformation):BOOL;
Первые два параметра - это имя запускаемого приложения и передаваемые ему  в
командной  строке  параметры.  Параметры  dwCreationFlags  содержит   флаги,
определяющие способ создания нового  процесса  и  его  приоритет.  Структура
lpStartupInfo  содержит  сведения   о   размере,   цвете,   положении   окна
создаваемого   приложения.   На   выходе   функции   заполняется   структура
lpProcessInformation.  В  ней  программисту   возвращаются   дескрипторы   и
идентификаторы созданного процесса и его первичного потока.
Локальные данные потока
Интересная проблема возникает, если в приложении будет несколько  одинаковых
потоков. Как избежать совместного использования одних и  тех  же  переменных
различными потоками? В первую очередь следует использовать  поля  объекта  –
потомка tThread. Каждый поток соответствует отдельному  экземпляру  объекта,
и их данные пересекаться не будут. Однако, может возникнуть необходимость  в
использовании функций API, которые знать не знают об объектах  Delphi  и  их
полях и свойствах. Для  поддержки  разделения  данных  на  нижнем  уровне  в
Object Pascal введена специальная директива - threadvar, которая  отличается
от обычной var тем,  что  применяется  только  к  локальным  данным  потока.
Следующее описание:


var data1:integer;

threadvar data2:integer;
Означает, что переменная data1 будет использоваться всеми  потоками  данного
приложения, а переменная data2 будет у каждого потока своя.
                       Ермаков P.В.  |Основные разделы
Пред.11121314
скачать работу

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

 

Отправка СМС бесплатно

На правах рекламы


ZERO.kz
 
Модератор сайта RESURS.KZ