МЕНЮ


Фестивали и конкурсы
Семинары
Издания
О МОДНТ
Приглашения
Поздравляем

НАУЧНЫЕ РАБОТЫ


  • Инновационный менеджмент
  • Инвестиции
  • ИГП
  • Земельное право
  • Журналистика
  • Жилищное право
  • Радиоэлектроника
  • Психология
  • Программирование и комп-ры
  • Предпринимательство
  • Право
  • Политология
  • Полиграфия
  • Педагогика
  • Оккультизм и уфология
  • Начертательная геометрия
  • Бухучет управленчучет
  • Биология
  • Бизнес-план
  • Безопасность жизнедеятельности
  • Банковское дело
  • АХД экпред финансы предприятий
  • Аудит
  • Ветеринария
  • Валютные отношения
  • Бухгалтерский учет и аудит
  • Ботаника и сельское хозяйство
  • Биржевое дело
  • Банковское дело
  • Астрономия
  • Архитектура
  • Арбитражный процесс
  • Безопасность жизнедеятельности
  • Административное право
  • Авиация и космонавтика
  • Кулинария
  • Наука и техника
  • Криминология
  • Криминалистика
  • Косметология
  • Коммуникации и связь
  • Кибернетика
  • Исторические личности
  • Информатика
  • Инвестиции
  • по Зоология
  • Журналистика
  • Карта сайта
  • Программирование на Delphi

    25, 'SharedBlock');

    if (hMappedFile = 0) then ShowMessage ('Mapping error !') else begin

    pSharedBuf:=MapViewOfFile(hMappedFile,FILE_MAP_ALL_ACCESS,0,0,0);

    if (pSharedBuf = nil) then ShowMessage ('MapView error');

    end;

    End;

    В этом примере выделяется 25 байт разделяемой памяти при помощи функции

    CreateFileMapping. Имя результирующего объекта файлового отображения будет

    SharedBlock. Если функция завершится успешно, то ссылка на новый

    отображаемый файл будет возвращена в переменную hMappedFile. Переменная

    hMappedFile имеет тип Thandle, если значение переменной hMappedFile равно

    нулю, то это означает, что функция отработала с ошибкой, о чем будет

    выведено соответствующее сообщение. Если значение не нулевое, то будет

    вызвана функция MapViewOfFile. Дескриптор hMappedFile является первым

    параметром этой функции и связывает созданный отображаемый файл с текущим

    процессом. Если функция завершится успешно, то в переменную pSharedBuf

    будет помещен начальный адрес памяти, по которому располагаются данные

    объекта файлового отображения с именем SharedBlock. Если функция отработает

    с ошибкой, то значение, возвращаемое функцией MapViewOfFile будет равно

    nil, в этом случае будет показано сообщение, констатирующее этот факт.

    Совместное использование отображаемых данных

    Чтобы разделить между процессами память, выделенную из страничного файла

    операционной системы, каждый процесс, участвующий в разделении, должен

    отобразить один и тот же фрагмент одного и того же файла. Такой результат

    может быть достигнут передачей во всех указанных процессах одинаковых

    параметров для функций CreateFileMapping и MapViewOfFile. Указатель,

    возвращаемый последней функцией, вы можете впоследствии считывать или

    записывать согласно своим потребностям. Если данные, связанные с этим

    указателем, доступны одному из процессов, то они также доступны и другим

    процессам.

    Займемся очередным "клонированием" нашего примера с передачей данных о

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

    описанный выше код по открытию и отображению файла. Он описан как реакция

    на событие формы onCreate. Когда запускается программа и создается форма,

    соответственно создается и подключается отображаемый файл. Код выглядит

    так:

    procedure TSrvForm.FormCreate (Sender: TObjecr);

    begin

    hFileMapObj:=CreateFiieMapping(MAXDWORD, nil, PAGE_READWRITE, 0, 25,

    'SharedMem');

    if (hFiieMapObj:=0) then ShowMessage('Error: cannot map this file')

    else begin

    pSharedBuf:=MapViewOfFile(hFiieMapObj,FILE_MAP_WRITE,0,0,0);

    if (pSharedBuf = nil) then

    ShowMessage ('Error: pSharedBuf is nil');

    end;

    end;

    Приведенный выше код работает точно так, как описано выше в разделе

    "Подключение объекта файлового отображения к адресному пространству".

    Единственным отличием является лишь то, что объявления переменных

    hFileMapObj и pSharedBuf перенесены в раздел var секции interface так, как

    это показано ниже:

    interface

    var Form1: TForm1;

    hFileMapObj: THandle;

    pSharedBuf; Pointer;

    implementation

    Компоненты типа TTimer есть и у клиента и у сервера. При каждом очередном

    событии от этого компонента сервер помещает нужные данные в совместно

    используемую область памяти:

    type

    pDataRecord = ^TDataRecord;

    TDataRecord = record

    DateTime : TDateTime;

    Mem : Cardinal ;

    end;

    procedure TServerForm.Timer1Timer(Sender: TObject);

    var ms : TMemoryStatus;

    begin

    GlobalMemoryStatus (ms);

    pDataRecord(pSharedBuf)^.DateTime:= Now;

    pDataRecord(pSharedBuf)^.Mem := ms.dwAvailPageFile + ms.dwAvaiiPhys;

    end;

    а клиент — читает эти данные, если нажата соответствующая кнопка:

    procedure TClientForm.TimerITimerfSender: TObject);

    begin

    if MemSpeedButton.Down then MemSpeedButton.Caption:=

    Format('%8dK',[pDataRecord(pSharedBuf)^.Mem div 1024]);

    if TimeSpeedButton.Down then TimeSpeedButton.Caption:=

    TimeToStr(pDataRecord(pSharedBuf)^.DateTime);

    end;

    Последним штрихом станет восстановление надписи на кнопке после того, как

    она снова нажата пользователем:

    procedure TClientForm.TimeSpeedButtonClick (Sender: TObject);

    begin

    if not TimeSpeedButton.Down then TimeSpeedButton.Caption:='Time';

    end;

    procedure TClientForm.Mem.SpeedButtonClick(Sender: TObject);

    begin

    if not MemSpeedButton. Down then MemSpeedButton.Caption:='Memory';

    end;

    В рассматриваемой программе есть несколько операторов, необходимых для

    прекращения отображения данных и освобождения объекта файлового

    отображения. Эти операторы обсуждаются в следующем разделе.

    Прекращение отображения данных и закрытие объекта файлового отображения

    Последние две функции, имеющие отношение к объекту файлового отображения,

    называются UnMapViewOfFile И CloseHandle. ФУНКЦИЯ UnMapViewOfFile делает

    то, что подразумевает ее название. Она прекращает отображение в адресное

    пространство процесса того файла, который перед этим был отображен при

    помощи функции MapViewOfFile. Функция CloseHandle также делает то, что

    подразумевает ее название; она закрывает дескриптор, в нашем случае это

    дескриптор объекта файлового отображения, возвращаемый функцией

    CreateFileMapping.

    Функция UnMapViewOfFile должна вызываться перед функцией CloseHandle

    Функции UnMapViewOfFile передается единственный параметр типа указатель:

    procedure TCIientForm.FormDestroy(Sender: TObject);

    begin

    UnMapViewOfFiie (pSharedBuf) ;

    CloseHandle (hFileMapObj);

    end;

    Помимо возможности совместного доступа отображаемые файлы позволяют заметно

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

    инструментом доступа к данным.

    Каналы

    Протокол DDE пережил полосу своего расцвета, и хотя впоследствии появилась

    его сетевая версия (Network DDE, или NDDE), стандартом де-факто она не

    стала. Одним из кандидатов на замену DDE стал механизм каналов (pipes). О

    его роли говорит хотя бы то, что это один из основных протоколов работы

    такого продукта, как Microsoft SQL Server.

    Сразу оговоримся, что каналы бывают двух видов — именованные (named pipes)

    и безымянные (anonymous pipes). Вторые не предназначены для связи между

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

    Win32 API. В этой книге рассматриваются только именованные каналы.

    И еще одна очень важная оговорка. Каналы рассматривались Microsoft как

    протокол для организации клиент-серверных приложений. Поэтому их серверная

    часть реализована только в среде Windows NT и не поддерживается в Windows

    95/98; клиенты могут быть созданы во всех этих ОС.

    Канал можно представить себе как среду, через которую могут обмениваться

    данными два приложения. Обмен данными может быть как односторонним, так и

    двухсторонним. Тем не менее, одно из приложений играет роль сервера (оно

    создает канал), другое (или другие) лишь подключается к нему. Противоречия

    с вышесказанной фразой о двух приложениях здесь нет: на сервере канал виден

    как ресурс с единственным уникальным именем. Когда к серверу подключается

    очередной клиент, для него создается уникальный экземпляр канала со своими

    дескриптором, буфером и т, п. Но имя канала для всех клиентов одинаково.

    Имя канала записывается в соответствии с так называемым соглашением UNC

    (Universal Naming Convention). Выглядеть оно должно так:

    \servername\pipe\pipename

    де servernanie — сетевое имя компьютера — сервера,

    ipename — имя канала.

    В случае, если клиенту нужно подключиться к серверу на том же компьютере,

    его сетевое имя заменяется точкой:

    \.\pipe\pipename

    Максимальная длина имени канала ограничена 256 символами; строчные и

    прописные буквы не отличаются.

    Для программиста алгоритмы создания серверного и клиентского "концов"

    канала отличаются. Для создания сервера применяются специальные функции Win

    32 API; клиентский же конец открывается как обычный файл и работа с ним

    также напоминает работу с файлом. Неудивительно, что в дальнейшем мы

    "упрячем" эти функции в класс Delphi — потомок HandleStream, ближайшего

    родственника файлового потока TFileStream.

    Пока же рассмотрим искомые функции API. Главная из них для нас следующая:

    function CreateNainedPipe(lpName: PChar;

    dwOperiMode,

    dwPipeMode,

    nMaxInstances,

    nOutBufferSize,

    nInBufferSize,

    nDefauitTimeOut: DWORD;

    lpSecurityAttributes:PSecurityAttributes):THandle;

    Она создает серверный конец канала с именем lpName. Остальные параметры

    перечислены в табл. 8.1.

    Параметры функции createNamedPipe

    Параметр Назначение

    dwOpenMode

    Режим открытия. Флаги:

    PIPE_ACCESS_DUPLEX — двунаправленный обмен данными

    PIPE_ACCESS_INBOUND — только от клиента к серверу

    PIPE_ACCESS_OUTBOUND — только от сервера к клиенту

    FILE_FLAG_WRITE_THROUGH — запись данных, минуя кэш

    FILE_FLAG_OVERLAPPED — режим отложенной операции ввода/ вывода

    dwPipeMode

    Режим работы канала. Флаги:

    PIPE_TYPE_BYTE — запись в режиме потока байт

    PIPE TYPE_MESSAGE — запись в режиме потока сообщений

    PIPE_READMODE_BYTE — чтение в режиме потока байт

    PIPE_READMODE_MESSAGE — чтение в режиме потока сообщений

    PIPE_WAIT — функции ввода/вывода не будут возвращать управление до

    завершения операции

    PIPE_NOWAIT — функции ввода/вывода возвращают управление немедленно

    nMaxinstances

    Максимальное количество открываемых экземпляров канала, от 1 до

    PIPE_UNLIMITED_INSTANCES

    nOutBufferSize

    Размер буфера для записи

    nInBufferSize

    Размер буфера для чтения

    nDefauitTimeOut

    Задает время ожидания конца операции ввода/вывода в канале (в мс)

    IpSecurityAttributes

    Указатель на структуру Windows NT, содержащую информацию о правах доступа к

    каналу Pежимы потока байт и потока сообщений не слишком отличаются друг от

    друга — в первом случае система смешивает данные от различных операций

    чтения/записи в единый поток, во втором — разделяет их на отдельные порции.

    Канал в режиме PIPE_TYPE_BYTE может работать на чтение только в режиме

    чтения PIPE_READMODE_BYTE, канал в режиме PIPE_TYPE_MESSAGE — в обоих

    режимах чтения.

    Функция

    function ConnectNainedPipe(hNamedPipe: THandle;

    lpOverlapped: POverlapped): BOOL;

    позволяет подключиться к уже созданному каналу hNamedPipe, а функция

    function DisconnectNaitledPipe (hNamedPipe: THandie): BOOL;

    позволяет отключить клиента — она разрывает связь клиентского и серверного

    концов канала hNamedPipe.

    Чтобы собрать информацию о состоянии канала hNamedPipe, нужно вызвать

    функцию

    function GetNamedPipeln.fo(hMamedPipe: THandle;

    var ipFlags: DWORD;

    lpOutBufferSize,

    lpInBufferSize,

    lpMaxInstances: Pointer): BOOL;

    Указатели lpOutBufferSize, lpInBufferSize, ipMaxInstances должны указывать

    на переменные, куда будут записаны размеры буферов и число открытых

    экземпляров канала. Параметр lpFlags указывает на переменную, в которую

    будут записаны флаги состояния канала. Среди них уже знакомый флаг

    PIPE_TYPE_MESSAGE, а также флаг PIPE_SERVER_END. Он установлен, если

    hNamedPipe — серверный конец канала.

    function PeekNamedPipe (hNamedPipe: THandle;

    lpBuffer: Pointer;

    nBufferSize: DWORD;

    lpBytesRead,

    lpTotalBytesAvail,

    lpBytesLeftThisMessage: Pointer): BOOL;

    Эта функция позволяет прочитать данные из буфера канала, оставив их там

    (доступными для последующего чтения). Кроме того, она возвращает

    дополнительную полезную информацию о состоянии канала, в частности по

    адресу, указанному в параметре lpTotalBytesAvail, будет записано число еще

    не прочитанных байт в канале. Функция

    Function WaitNamedPipe(lpNamedPipeName: PChar; nTimeOut: DWORD): BOOL;

    позволяет организовать ожидание окончания операции в канале. Параметр

    nTimeOut задает время ожидания в миллисекундах; возможны еще два особых

    значения — NMPWAIT_USE_DEFAULT_WAIT (ожидать в течение времени, указаного

    при создании канала) и NMPWAIT_WAIT_FOREVER (ждать бесконечно).

    Осталось добавить, что чтение и запись в канал осуществляется так же, как и

    в обычный файл — функциями ReadFile и WriteFile.

    Каналы хорошо приспособлены для обмена данными в сети. Но все же их

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

    Поэтому в глобальных сетях применяется другой вариант механизма

    межзадачного взаимодействия — сокеты.

    4. Многопоточные приложения

    Потоки - это объекты, получающие время процессора. Потоки позволяют в

    рамках одной программы решать несколько задач одновременно. Операционная

    система предоставляет приложению некоторый интервал времени центрального

    процессора (называемый квантом) и в момент, когда приложение переходит к

    ожиданию сообщений или освобождает процессор, ОС передает управление другой

    задаче. Планируя время центрального процессора, Windows распределяет его

    межу потоками, а не между приложениями. Время процессора выделяется

    квантами (около 19 мс). Чтобы использовать все возможности операционной

    системы, программист должен знать, как создавать потоки.

    Существует два типа потоков: асимметричные и симметричные.

    Асимметричные потоки (asymmetric threads) решают различные задачи, и, как

    правило, не разделяют совместные ресурсы.

    Симметричные потоки (symmetric threads) выполняют одну и ту же работу,

    разделяет одни и те же ресурсы и исполняют один код. Пример приложения с

    симметричными потоками - электронные доски объявлений (Bulletin Board

    Systems, BBS). Для обслуживания каждого дозвонившегося туда пользователя

    BBS запускает новый поток.

    Программа в терминах операционной системы представляет собой процесс.

    Процесс - это совокупность виртуальной памяти, исполняемого кода, потоков и

    данных. Процесс должен содержать по крайней мере один поток.

    Если задачи приложения можно органично разделить на различные подмножества:

    обработка событий, ввод-вывод, связь и т.д., то потоки могут быть органично

    встроены в программное решение. Сделав приложение многопоточным,

    программист получает дополнительные возможности управления им. Например,

    через управление приоритетами потоков. Другое важное преимущество

    использования потоков - при возрастании "нагрузки" на приложение можно

    увеличить их количество и можно увеличить их количество, и, тем самым,

    снять проблему.

    Две типичные проблемы, с которыми может столкнуться программист при работе

    с потоками - это ситуации тупиков и гонок.

    Гонки

    Ситуация гонок возникает, когда два или более потоков пытаются получить

    доступ к общему ресурсу и изменить его состояние. ассмотрим следующий

    пример. Пусть поток 1 получил доступ к ресурсу и изменил его в своих

    интересах; затем активизировался поток 2 и модифицировал этот же ресурс до

    завершения потока 1. Поток 1 полагает, что ресурс остался в том же

    состоянии, в котором он был до переключения (строго говоря, потоку 1 вообще

    ничего не известно о переключении). В зависимости от того, когда был

    изменен ресурс, результаты будут варьироваться - иногда код будет

    выполняться правильно, иногда - нет. Программист не должен строить никаких

    иллюзий по поводу выполнения потоков, т.к. планировщик ОС может запускать

    их и останавливать в любое время.

    Тупики

    Тупики имеют место, когда поток ожидает ресурс, который в данный момент

    принадлежит другому потоку. ассмотрим пример: поток 1 захватывает объект А

    и, для того, чтобы продолжать работу, ждет возможности захватить объект Б.

    В то же время, поток 2 захватывает объект Б и ждет возможности захватить

    объект А. В результате оба потока оказываются заблокированными - ни один из

    них не будет выполняться. Для исключения ситуаций тупиков и гонок потоки

    следует синхронизировать.

    Приоритеты потоков

    Операционная система планирует время в соответствии с приоритетами потоков.

    Когда поток создается, ему назначается приоритет, соответствующий

    приоритету породившего его процесса. Процессы, в свою очередь, имеют

    следующие классы приоритетов:

    1. Pеального времени (Real Time). Этот класс определяет приоритет даже

    больший, чем у многих процессов операционной системы. Такой процесс

    необходим для процессов, обрабатывающих высокоскоростные потоки данных.

    2. Высокий (High). Этот класс определяет приоритет выше нормального. Он

    используется процессами, которые должны завершиться за короткое время.

    3. Нормальный (Normal). Большинство процессов запускается в рамках этого

    класса.

    4. Фоновый (Idle). Процессы с таким приоритетом запускаются только в

    случае, если в очереди диспетчера задач нет других процессов. Программисты

    могут использовать этот класс приоритетов для организации фоновых процедур

    и реорганизации данных. Примером может служить проверка орфографии и

    сохранение файла в MS Word.

    Приоритеты имеют значения от 0 до 31. Приоритет потока может отличаться от

    приоритета породившего его процесса на плюс-минус две единицы.

    Соответствующие величины показаны ниже.

    Низший

    Пониженный

    Нормальный

    Повышенный

    Высший

    Фоновый

    2

    3

    4

    5

    6

    Нормальный заднего плана

    5

    6

    7

    8

    9

    Нормальный переднего плана

    7

    8

    9

    10

    11

    Высокий

    11

    12

    13

    14

    15

    Реального времени

    22

    23

    24

    25

    26

    Класс tThread

    Нужно отдавать себе отчет, что с точки зрения операционной системы, поток -

    это ее объект. При создании он получает дескриптор и отслеживается ОС.

    Объект класса tThread - это конструкция Delphi, соответствующая потоку ОС.

    Для создания потока служит конструктор

    Constructor Create(CreateSuspended:Boolean);

    Если параметр CreateSuspended равен TRUE, вновь созданный поток не начинает

    выполняться до тех пор, пока не будет вызван метод Resume. В противном

    случае сразу после создания поток начинает исполнение.

    Метод Procedure Resume;

    класса tThread вызывается, когда поток возобновляется после остановки, или

    если он был создан конструктором с параметром CreateSuspended, равным TRUE.

    Вызов метода

    Procedure Suspend;

    Приостанавливает поток с возможностью повторного запуска в последствии.

    Выполнение продолжается с точки останова.

    Свойство Property Suspended:boolean;

    Позволяет программисту определить, не приостановлен ли поток. С помощью

    этого свойства можно также запускать и останавливать поток.

    Для окончательного завершения потока (без последующего запуска) существует

    метод

    procedure Terminate;

    он останавливает поток и возвращает управление вызвавшему его процессу

    только после того, как это произошло. Свойство

    property Terminated:boolean;

    позволяет узнать, вызывался ли уже метод Terminate.

    Метод Function WaitFor: integer;

    Предназначен для синхронизации и позволяет одному потоку дождаться момента,

    когда завершится другой. Если внутри потока FirstThread написать код:

    Code:=SecondThread.WaitFor;

    то это означает, что поток FirstThread останавливается до завершения потока

    SecondThread . Метод WaitFor возвращает значение свойства ReturnValue.

    Свойство Property Priority: tThreadPriority;

    Определяет приоритет потока. Допустимыми значениями приоритета являются:

    tpIdle, tpLowest, tpLower, tpNormal, tpHigher, tpHighest, tpTimeCritrcal.

    Метод Procedure Synchronyze(Method: tTHreadMethod);

    предназначен для безопасного вызова методов VCL внутри потоков. Этот метод

    гарантирует, что к каждому объекту VCL одновременно имеет доступ только

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

    метод Synchronyze - это имя метода, который производит обращение к VCL.

    Вызов Synchronyze с таким аргументом, это то же самое, что и вызов самого

    метода. Synchronyze находится в области видимости protected, и,

    следовательно, доступен только в методах потомков класса tThread.

    Главным методом класса tThread является абстрактный метод

    Procedure Execute; virtual; abstract;

    Этот метод должен быть переопределен в классе-потомке tThread. В его теле

    должен содержаться код, который и представляет собой собственно поток. Если

    поток был создан с аргументом 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.В. |Основные разделы

    Железо:

    > раздел hardware

    Обзоры программ:

    > раздел software

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

    > раздел programming

    Операционные системы:

    > раздел ОС

    Графика и дизайн:

    > раздел graphics

    Сетевые технологии:

    > раздел network

    | |

    Страницы: 1, 2, 3, 4, 5, 6, 7


    Приглашения

    09.12.2013 - 16.12.2013

    Международный конкурс хореографического искусства в рамках Международного фестиваля искусств «РОЖДЕСТВЕНСКАЯ АНДОРРА»

    09.12.2013 - 16.12.2013

    Международный конкурс хорового искусства в АНДОРРЕ «РОЖДЕСТВЕНСКАЯ АНДОРРА»




    Copyright © 2012 г.
    При использовании материалов - ссылка на сайт обязательна.