Главная » Delphi » Приостановка и возобновление потока

0

Давайте вспомним, что  говорилось в этой  главе  ранее о конструкторе Create() класса TThread. Как уже было сказано, поток  может быть создан в приостановленном состоянии, и для того  чтобы  он начал  выполняться, необходимо вызвать метод  Re- sume(). Логично предположить, что  поток  может  быть  приостановлен и возобнов лен динамически. Эта задача решается с помощью  методов Suspend() и Resume().

Хронометраж потока

Когда то,  во  времена 16 разрядных приложений для  Windows  3.x,  было  принято создавать оболочки для некоторых участков  кода, которые с помощью функций Get- TickCount() и timeGetTime() позволяли определить, сколько  времени отнимает выполнение определенного вычисления. Например:

var

StartTime, Total: Longint;

begin

StartTime := GetTickCount;{ Здесь выполняются вычисления } Total := GetTickCount – StartTime;

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

Во избежание подобных проблем в системе Win32 (вариант Windows NT/2000) предусмотрена функция GetThreadTimes(), благодаря которой можно  получить до вольно  подробную информацию о времени выполнения потока. Объявление этой функции имеет следующий вид:

function GetThreadTimes(hThread: THandle; var lpCreationTime, lpExitTime, lpKernelTime,

lpUserTime: TFileTime): BOOL; stdcall;

Параметр hThread представляет собой  дескриптор потока, для которого необхо димо  получить информацию о времени выполнения. Другие  параметры передаются по ссылке и заполняются функцией. Рассмотрим каждый из них:

•  lpCreationTime. Время создания потока.

•    lpExitTime. Время окончания работы потока. Если поток продолжает выпол

няется, это значение не определено.

•  lpKernelTime. Время, затраченное потоком на выполнение кода операционной системы.

•  lpUserTime. Время,  затраченное потоком на выполнение кода приложения.

Этих четыре параметра имеют  тип TFileTime, который определен в модуле Win- dows следующим образом:

type

TFileTime = record

dwLowDateTime: DWORD;

dwHighDateTime: DWORD;

end;

Определение  данного типа  несколько необычно,  но  это  часть  интерфейса  API Win32,  и  с  этим  придется мириться. Элементы записи dwLowDateTime и  dwHigh- DateTime объединяются в учетверенное слово  и  образуют   64 разрядное значение, представляющее количество 100 наносекундных интервалов,  прошедших с 1 января

1601 года. Это означает, что если бы потребовалось смоделировать движение англий ского  флота, который нанес  поражение испанской армаде  в 1588 году, то  тип  TFi- leTime был  бы  совершенно  неприемлем  для  отслеживания  значений  времени… Впрочем, мы несколько отвлеклись.

CОВЕТ

Поскольку тип TFileTime является 64-разрядным, то для выполнения арифметиче-

ских действий над значениями этого типа можно использовать операцию приведениятипа TFileTime к типу Int64. Следующий пример демонстрирует возможный способ быстрого сравнения значений типа TFileTime:

if Int64(UserTime) > Int64(KernelTime) then Beep;

Для упрощения работы со значениями TFileTime в среде  Delphi  существует  ряд функций,  позволяющих  выполнять  преобразования   между  типами  TFileTime и TDateTime в прямом и обратном направлениях:

function FileTimeToDateTime(FileTime: TFileTime): TDateTime;

var

SysTime: TSystemTime;

begin

if not FileTimeToSystemTime(FileTime, SysTime) then

raise EConvertError.CreateFmt(‘FileTimeToSystemTime failed. ‘

+ ‘Error code %d’, [GetLastError]);

with SysTime do

Result := EncodeDate(wYear, wMonth, wDay) +

EncodeTime(wHour, wMinute, wSecond, wMilliseconds)

end;

function DateTimeToFileTime(DateTime: TDateTime): TFileTime;

var

SysTime: TSystemTime;

begin

with SysTime do begin

DecodeDate(DateTime, wYear, wMonth, wDay);

DecodeTime(DateTime, wHour, wMinute, wSecond, wMilliseconds);

wDayOfWeek := DayOfWeek(DateTime);

end;

if not SystemTimeToFileTime(SysTime, Result) then

raise EConvertError.CreateFmt(‘SystemTimeToFileTime failed. ‘

+ ‘Error code %d’, [GetLastError]);

end;

CОВЕТ

Не забывайте, что функция GetThreadTimes() реализована только в Windows NT/2000. При ее вызове в среде Windows 95/98 всегда возвращается значение False. К сожалению, в Windows 95/98 не предусмотрен механизм получения информации о времени выполнения по- токов.

Управление несколькими потоками

Как уже отмечалось, несмотря на то что с помощью потоков можно  решить множе ство задач программирования, они приносят с собой новые  типы  проблем, с которыми приходится встречаться в создаваемых приложениях. Чаще  всего эти новые  проблемы связаны с доступом  со стороны нескольких потоков к таким  глобальным ресурсам, как глобальные переменные или  дескрипторы. Кроме  того,  проблемы могут возникнуть в том случае, когда, например, нужно обеспечить постоянное возникновение некоторого события в одном потоке перед или после некоторого другого события во втором пото ке. В настоящем разделе обсудим, как решить эти вопросы, используя средства, предос тавленные в Delphi для хранения локальных переменных потоков, а также средства API, предназначенные для синхронизации потоков.

Источник: Тейксейра, Стив, Пачеко, Ксавье.   Borland Delphi 6. Руководство разработчика. : Пер.  с англ. — М. : Издательский дом “Вильямс”, 2002. —  1120 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии