Создание многопоточных приложений. Копытин А.В - 13 стр.

UptoLike

Составители: 

13
Первый, и самый простой, состоит в использовании локальных переменных
(в стеке). Поскольку каждый поток получает собственный стек, то при выпол-
нении одной процедуры или функции он будет иметь и собственную копию ло -
кальных переменных. Второй метод заключается в сохранении локальной ин-
формации в объекте потомка класса TThread. И , наконец , можно также исполь -
зовать зарезервированное слово Delphi threadvar, чтобы воспользоваться пре-
имуществами хранения локальной информации потока на уровне операционной
системы .
Использование объекта TThread для хранения данных
Если сравнивать последние два варианта хранения данных потоков, то , бес-
спорно , следует остановить выбор на способе хранения данных в объекте по -
томка класса TThread, поскольку он проще и эффективнее метода с использо -
ванием зарезервированного слова threadvar (речь о нем пойдет позже). А для
объявления локальных данных потока более предпочтительным способом дос-
таточно добавить их в определение потомка класса TThread:
type
TMyThread = class(TThread)
private
FLocallnt: Integer;
FLocalStr: String;
end;
threadvar: хранение локальных данных потоков с помо-
щью интерфейса API
Выше упоминалось о том, что каждому потоку для хранения локальных пе-
ременных предоставляется его собственный стек , в то время как глобальные
данные должны совместно использоваться всеми потоками внутри приложения.
Например, у вас есть процедура, которая устанавливает или отображает значе -
ние глобальной переменной, причем она построена так , что при передаче ей
текстовой строки происходит установка, а при передаче пустой строки— ото -
бражение этой глобальной переменной. Такая процедура может иметь следую -
щий вид:
var GlobalStr: String;
procedure SetShowStr(const S: String);
begin
if S = " then
MessageBox(0, PChar(GlobalStr), 'The string is...', MB_0K) else
GlobalStr := S;
end;
Если эта процедура вызывается в контексте только одного потока, никаких
проблем не возникнет. Один раз она будет вызвана для установки значения пе-
ременной GlobalStr, а второй— для отображения этого значения. Давайте раз -
беремся , что же произойдет, если два или больше потоков смогут вызвать эту
процедуру в произвольный момент времени . В этом случае возможна ситуация,
когда один поток вызовет эту процедуру для установки строки, после чего про -
                                         13
П ервы й, и самы й про стой, со стоитв испо льзо вании ло кальны х переменны х
(в стеке). П о ско льку каж ды й по ток по лучаетсо бственны й стек, то при вы по л-
нении о дно й про цедуры или функции о н будетиметьи со бственную ко пию ло -
кальны х переменны х . В торо й метод заклю чается в со х ранении ло кально й ин-
фо рмации во бъ екте по томкаклассаTThread. И , нако нец, мо ж но такж е испо ль-
зо вать зарезервиро ванно е сло во Delphi threadvar, чтобы во спо льзо ваться пре-
имущ ествами х ранения ло кально й инфо рмации по токанауро вне о перацио нно й
системы .

Ис п ользован и е об ъект аTThread для хран ен и я дан н ы х
   Е сли сравнивать по следние два варианта х ранения данны х по токо в, то, бес-
спо рно , следуето стано вить вы бо р на спо со бе х ранения данны х в о бъ екте по -
томка класса TThread, по ско льку о н про щ е и эффективнее метода с испо льзо -
ванием зарезервиро ванно го сло ва threadvar (речь о нем по йдетпо зж е). А для
о бъ явления ло кальны х данны х по тока бо лее предпо чтительны м спо со бо м до с-
таточно до бавитьих во пределениепо томкаклассаTThread:
type
  TMyThread = class(TThread)
  private
    FLocallnt: Integer;
    FLocalStr: String;
  end;

threadvar: хран ен и е локальн ы х дан н ы х п от оков с п ом о-
щ ьюи н т ерфейс аAPI
   В ы ш е упо минало сь о том, что каж до му по току для х ранения ло кальны х пе-
ременны х предо ставляется его со бственны й стек, в то время как гло бальны е
данны е до лж ны со вместно испо льзо ваться всеми по токами внутри прило ж ения.
Н апример, у вас есть про ц едура, ко торая устанавливаетили о тображ аетзначе-
ние гло бально й переменно й, причем о на по стро ена так, что при передаче ей
текстово й стро ки про исх о дитустано вка, а при передаче пустой стро ки— о то-
браж ение этой гло бально й переменно й. Т акая про цедура мо ж етиметь следую -
щ ий вид:
var GlobalStr: String;
procedure SetShowStr(const S: String);
begin
  if S = " then
  MessageBox(0, PChar(GlobalStr), 'The string is...', MB_0K) else
  GlobalStr := S;
end;
   Е сли эта про цедура вы зы вается в ко нтексте только о дно го по тока, никаких
про блем не во зникнет. О дин раз о набудетвы званадля устано вки значения пе-
ременно й GlobalStr, авторо й— для о тображ ения этого значения. Д авайте раз-
беремся, что ж е про изо йдет, если два или бо льш е по токо в смо гутвы звать эту
про цедуру впро изво льны й мо ментвремени. В этом случае во змо ж наситуац ия,
ко гдао дин по ток вы зо ветэтупро ц едуру для устано вки стро ки, по сле чего про -