inherited delphi что это

Inherited delphi что это

2. Create(arguments);
begin
Inherited Create(arguments); // Всегда вызывается в начале конструктора
.
end;

3. Destroy
begin
.
Inherited; // Всегда вызывается в начале конструктора
end;

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

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

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

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

Похожие команды
Class Начинает объявление типа объектного класса

Constructor Определяет метод используемый для создания объекта из класса

Destructor Определяет метод используемый для уничтожения объекта

Function Определяет подпрограмму, которая возвращает значение

Object Позволяет данным типа подпрограмм обращаться к методу объекта

Overload Позволяет 2-м или более подпрограммам иметь одинаковое название

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

Procedure Определяет подпрограмму, которая не возвращает значение

Источник

Справочник функций и процедур Delphi: Inherited

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

1. Create;
begin
Inherited; // Всегда вызывается в начале конструктора
.
end;

2. Create(arguments);
begin
Inherited Create(arguments); // Всегда вызывается в начале конструктора
.
end;

3. Destroy
begin
.
Inherited; // Всегда вызывается в начале конструктора
end;

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

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

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

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

Похожие команды
Class Начинает объявление типа объектного класса

Constructor Определяет метод используемый для создания объекта из класса

Destructor Определяет метод используемый для уничтожения объекта

Function Определяет подпрограмму, которая возвращает значение

Object Позволяет данным типа подпрограмм обращаться к методу объекта

Overload Позволяет 2-м или более подпрограммам иметь одинаковое название

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

Procedure Определяет подпрограмму, которая не возвращает значение

Источник

Delphi создание объекта

Delphi 7. Занятие 2_7. Часть 3.

Как отмечалось ранее, экземпляры объектов создаются с помощью статического метода класса «create». Далее рассмотрим различные варианты применения этого метода.

Delphi создание экземпляра класса

Определим два новых класса.

Первый класс наследуем от TObject. Добавляем поле ii:integer;.

TMyClassA=class(TObject) //если наследование идёт от TObject, то можно просто записать TMyClassA=class

ii:integer;

Второй класс наследуем от первого и добавляем поле ss:string;

TMyClassB=class(TMyClassA)

ss:string;

В обработчике клика по кнопке создаём экземпляры объектов этих классов и выводим интересующие нас значения:

procedure TForm1.Button1Click(Sender: TObject);

var vA:TMyClassA; vB:TMyClassB;

vA:=TMyClassA.Create;

vB:=TMyClassB.Create;

В результате будем иметь:

В поле 1) отображено значение поля ii объекта vA.

В объект vB введено поле ss, а также унаследовано поле ii. Значение поля ii объекта vB отображено в поле 2).

В поле 3) отображено значение поля ss объекта vB.

В полях 4,5,6 и 7 отображено значение, возвращаемое функцией класса ClassName, вызываемой как непосредственно ссылкой из класса (значения 4 и 5), как и через экземпляр класса (значения 6 и 7).

В приведённом примере при создании экземпляра объекта vA вызывался конструктор из класса-родителя TObject.

Для класса TMyClassB родителем является класс TMyClassA. Так как в классе TMyClassA конструктор явно не задан, то берётся конструктор от его родителя — класса TObject.

Delphi конструктор класса

Пусть теперь в первом классе, порожденном от TObject, задан свой конструктор create.

constructor create;

Реализация тела конструктора:

constructor TMyClassC.create;

kk:=30; //задаём начальное значение поля;

procedure TForm1.Button2Click(Sender: TObject);

var vC:TMyClassC; vD:TMyClassD;

Как видно из кода, после создания экземпляра объекта vC его полю kk значение явно не присваивается.

Явно присваиваются значения полям kk и st объекта vD.

Вызов конструктора для класса TMyClassD.create влечёт за собой вызов конструктора класса-родителя TMyClassC:

constructor TMyClassC.create;

kk:=30; //задаём начальное значение поля;

Прежде, чем начнёт выполняться тело конструктора TMyClassC.create, будет вызван конструктор класса-родителя (то есть конструктор из TObject) и будет создан объект vD.

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

В данном случае выполнится инициализация поля kk:=30;

Это видно из приведенного примера:

Хотя полю vD.kk значение явно не задаётся, однако его определяет конструктор класса-родителя.

Если добавить оператор:

то результат будет следующим:

Теперь создадим оба класса с конструкторами.

constructor create;

constructor create;

constructor TMyClassG.create;

constructor TMyClassH.create;

И создание объектов:

procedure TForm1.Button4Click(Sender: TObject);

var vG:TMyClassG; vH:TMyClassH;

Поля 1, 2 и 3 сформированы конструктором. Поля 4, 5, и 6 отображают значения, заданные непосредственно для экземпляров объектов.

Теперь рассмотрим ситуацию:

constructor TMyClassM.create;

constructor TMyClassN.create;

procedure TForm1.Button5Click(Sender: TObject);

var vM:TMyClassM; vN:TMyClassN;

Оба класса имеют конструктор. Но конструктор класса TMyClassM определяет значение поля: nn:=60;. А в конструкторе TMyClassN этого поля нет. Тогда будем иметь следующий результат:

constructor TMyClassN.create;

поле nn не инициализируется, и начальное значение не передаётся из конструктора родительского класса.

Delphi inherited

Чтобы исправить ситуацию, надо использовать конструктор класса delphi, унаследованный от класса-родителя.

Для этого необходимо использовать ключевое слово «inherited» (унаследованный):

constructor TMyClassN.create;

inherited create; // вызываем конструктор, унаследованный от TMyClassM;

В результате будем иметь:

Наконец, рассмотрим конструктор с параметрами.

constructor create(n:integer=5);

constructor create(s:string;nm:integer=88);

constructor TmyClassP.create(n:integer=5); //параметр имеет значение по умолчанию

constructor TMyClassQ.create(s:string;nm:integer=88); //параметр имеет значение по умолчанию

procedure TForm1.Button6Click(Sender: TObject);

var vP:TMyClassP; vQ:TMyClassQ;

В результате имеем:

Так как параметры конcтруктора имеют значения по умолчанию, организуем вызов конструкторов в следующем виде:

Источник

Как работает inherited?

Как работает и что делает ключевое слово inherited?
Я читал справочник, книгу Алексеевой Чесноковой, вот http://wiki.lazarus.freepascal.org/inherited и.

Виртуальные методы и inherited
Насколько я понял основное преимущество виртуальных методов в делфи это возможность переопределять.

Решение

The reserved word inherited plays a special role in implementing polymorphic behavior. It can occur in method definitions, with or without an identifier after it.

If inherited is followed by the name of a member, it represents a normal method call or reference to a property or field, except that the search for the referenced member begins with the immediate ancestor of the enclosing method’s class. For example, when:

occurs in the definition of a method, it calls the inherited Create.

When inherited has no identifier after it, it refers to the inherited method with the same name as the enclosing method or, if the enclosing method is a message handler, to the inherited message handler for the same message. In this case, inherited takes no explicit parameters, but passes to the inherited method the same parameters with which the enclosing method was called. For example:

Зарезервированное слово inherited играет особую роль в реализации полиморфного поведения. Оно может встречаться в определении методов, с (или без) идентификатором после него.

Если за inherited следует название члена класса, он представляет собой обычный вызов метода или ссылку на свойство или поле класса, за исключением того, что поиск метода/свойства/поля начинается с непосредственного предка класса, в методе которого расположен вызов Inherited. Например, если:

происходит в определении метода, будет вызван унаследованный метод Create.

Когда за inherited не следует идентификатор, он относится к унаследованному методу с тем же именем, что и метод, где находится inherited, или (если он находится в обработчике сообщений) к унаследованному обработчику того же сообщения. В этом случае явно параметры для inherited не указываются, но в унаследованный метод передаются те же параметры, которые были переданы туда, откуда inherited вызывается.

Источник

Inherited delphi что это

Есть у меня поток:
Метод Free я обьявляю так:

destructor TScriptThread.Destroy;
begin
inherited;
fFindedList.Free;
fIgnoreList.Free;
//inherited Destroy;
end;


TUser © ( 2005-05-30 15:21 ) [1]


Mouserx ( 2005-05-30 15:21 ) [2]


> Метод Free я обьявляю так:

Имелось ввиду деструктор Destroy.


Defunct © ( 2005-05-30 15:21 ) [4]

Метод Free я обьявляю так:
destructor TScriptThread.Destroy;

Замечательное объявление метода Free! 🙂

inherited рекомендуется в конце.

Хотя, все на самом деле зависит от Ваших потребностей.
Может быть и в начале.
Частично зависит от того, где создаются объекты fFindedList и sIgnoreList: если Вас угораздило создавать их в конструкторе перед вызовом inherited Create, то и удалять их надо, скорее всего, после inherited Destroy;. По принципу FIFO :).


> Inherited вызывает обработчик предка

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


> Где он должен стоять в моем варианте? в начале или в конце?

где угодно.
в отрыве от остального кода говорить об этом бессмысленно


TUser © ( 2005-05-30 15:26 ) [7]

На самом деле, дажде если не написать Inherited, то вызов унаследованного деструктора все равно происходит. По крайней мере в D7.


> TUser © (30.05.05 15:26) [7]
> На самом деле, дажде если не написать Inherited, то вызов
> унаследованного деструктора все равно происходит. По крайней
> мере в D7.


Mouserx ( 2005-05-30 15:31 ) [9]

Вот мой коснструктор Create:

constructor TScriptThread.Create(Sender : TObject);
begin
inherited Create(True); <Поток создаем в состоянии «Приостановлен»>
FreeOnTerminate := True; <Поток освободит ресурсы при окончании работы>
fFindedList := TStringList.Create;
fIgnoreList := TStringList.Create;
Thread := Self;
Self.Priority := tpNormal; <Стартуем с нормальным приоритетом>
Resume; <Переводим поток в состояние «Активен»>
end;

В данном случае 2 TStringList я создаю после inherited Create(True);
Т.е как я понял освобождать их надо до Inherited Destroy.
Так?

Их же надо освобождать именно из дополнительного потока а не из основного. Что я не так сделал и не понял?

> Digitman © (30.05.05 15:28) [8]

Может я чего-то не понял. Написал

destructor TForm1.Create;
begin
.
end;

без inherited. Поставил Use Debug DCUs. И отладчик зашел в деструктор предка.


Defunct © ( 2005-05-30 15:34 ) [11]

Mouserx (30.05.05 15:31) [9]

> Ну и поосвобождает 2 TSctrinList, работу с которыми я не закончил.

Используйте событие OnTerminate для уверенности. После обработки данных вызывайте Free.


TUser © ( 2005-05-30 15:35 ) [12]

> Mouserx (30.05.05 15:31) [9]

Они в дополнительном потоке и освободятся. По логике, если FreeOnTerminate = true, то не надо вызывать Free из основного потока, а надо писать Terminate;


Defunct © ( 2005-05-30 15:36 ) [13]


Mouserx ( 2005-05-30 15:36 ) [14]


> Используйте событие OnTerminate для уверенности

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

какую-то галиматью ты написал)


Defunct © ( 2005-05-30 15:38 ) [16]

Mouserx (30.05.05 15:36) [14]

Да, это событие происходит после окончания работы метода Execute


Mouserx ( 2005-05-30 15:42 ) [17]


> Используйте событие OnTerminate для уверенности. После обработки
> данных вызывайте Free

После метода Execute вызывается деструктор Destroy.
А зачем еще вызывать Free?


-=XP=- © ( 2005-05-30 15:43 ) [18]

Третья заповедь: Прежде чем рубить ветку, убедитесь, что Вы на ней не сидите (С) Энциклопедия юных сурков

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


-=XP=- © ( 2005-05-30 15:47 ) [20]

По-моему, мы сейчас обсуждаем «через какую дверь лучше всего входить в метро».


Mouserx ( 2005-05-30 15:48 ) [21]

Но зачем Tread.Free если поток сам освободится?
Tread.Free приведет к ошибке.

Да и насчет использования этой конструкции:
А если поток будет в состоянии ожидания Sinchronize()?

Получиться что поток ждет, пока освободится основной поток для выполнения Sinchronize() а тот в свою очередь ждет (Thread.WaitFor) пока закончит работу дополнительный поток


Defunct © ( 2005-05-30 15:50 ) [22]

Digitman © (30.05.05 15:43) [19]

Но что мешает сделать так:

IMHO в деструкторе всегда inherited в конце, ничему не навредит и всегда будет работать. В крайнем случае можно засунуть inherited в finally.


Mouserx ( 2005-05-30 15:51 ) [23]

Digitman © (30.05.05 15:43) [19]
Задача такова. Есть дополнительный поток, в котором производяться медленные стороние вычисления.

Основной поток вызывает его используя метод Create. При этом в основном потоке в Destroy необходимо остановить и доп. потоки. Поэтому там для всех созданных доп. потоков я вызывал просто метод Free каждому.


Defunct © ( 2005-05-30 15:54 ) [25]

Mouserx (30.05.05 15:51) [23]
> Поэтому там для всех созданных доп. потоков я вызывал просто метод Free каждому.

Чревато AV ошибками на выходе из программы.


> При этом в основном потоке в Destroy


> Defunct © (30.05.05 15:50) [22]


> в деструкторе всегда inherited в конце, ничему не навредит
> и всегда будет работать

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


-=XP=- © ( 2005-05-30 16:07 ) [28]

Это понятно. Но зачем Tread.Free если поток сам освободится? Tread.Free приведет к ошибке.

При этом в основном потоке в Destroy необходимо остановить и доп. потоки. Поэтому там для всех созданных доп. потоков я вызывал просто метод Free каждому.

Вы сами себе противоречите.


Mouserx ( 2005-05-30 16:08 ) [29]


jack128 © ( 2005-05-30 16:10 ) [30]

Defunct © (30.05.05 15:50) [22]
IMHO в деструкторе всегда inherited в конце, ничему не навредит и всегда будет работать. В крайнем случае можно засунуть inherited в finally.

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


Defunct © ( 2005-05-30 16:13 ) [31]

Digitman © (30.05.05 15:59) [27]

типовой схемой в таких случаях всегда считал такую

опять же IMHO, из-вне выгоднее выполнить защищенное разрущение.


Mouserx ( 2005-05-30 16:13 ) [32]

В дестрое моего класса, созданного в основном потоке, который считает данные с доп. потоков и контролирует их работу. сам он освобождается в Form.Close или когда закончил работу.


Defunct © ( 2005-05-30 16:15 ) [33]

jack128 © (30.05.05 16:10) [30]

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


> Defunct © (30.05.05 16:13) [31]
> Digitman © (30.05.05 15:59) [27]
>
> типовой схемой в таких случаях всегда считал такую

она, может, и будет типовой, если КС не является временным ресурсом, созданным самим разрушаемым объектом

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

и при этом inherited в них должен ПРЕДшествовать освобождению ресурсов, занятых в конструкторах потоков и используемых в теле поточной ф-ции


Mouserx ( 2005-05-30 16:23 ) [36]

Кто мне может всетаки подсказать как правильно спроэктировать доп. поток и как правильно его «убивать» из вне?


Mouserx ( 2005-05-30 16:27 ) [37]


> ну вот там, в деструкторе своего класса и вызывай деструкторы
> потоков.

Просто Thread.Destroy?
Не противоречит ли с [21]?


> и при этом inherited в них должен ПРЕДшествовать освобождению
> ресурсов

Т.е в начале.


Defunct © ( 2005-05-30 16:28 ) [38]

Mouserx (30.05.05 16:23) [36]

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

критерия «правильности» нет.

есть критерии надежности, работоспособности, эффективности использования

посмотри демо-проект (%DELPHI%)\demos\threads\thrddemo.dpr


> Mouserx (30.05.05 16:27) [37]
> Просто Thread.Destroy?
> Не противоречит ли с [21]?

да, просто Thread.Free

нет, не противоречит, если FreeOnTerminate=False

но ДО того как ты уничтожишь ресурсы, к которым доп.поток обращается в ходе работы


Mouserx ( 2005-05-30 16:37 ) [41]

Digitman © (30.05.05 16:32) [40]

Из вне так будет хорошо работать, но как доп. поток освободит ресурсы сам, если FreeOnTerminate=False. Например когда он закончит с расчетами.


evvcom © ( 2005-05-30 16:40 ) [42]


> как доп. поток освободит ресурсы сам

Освобождай в Destroy. Как вызовешь Free, так и освободит.


Mouserx ( 2005-05-30 16:42 ) [43]


> Как вызовешь Free, так и освободит.

Т.е в конце метода Execute необходимо написать Self.Free?


> Mouserx (30.05.05 16:42) [43]
> Т.е в конце метода Execute необходимо написать Self.Free?

метод Free поточного объекта ты вызовешь в деструкторе своего контролирующего потоки объекта, при этом сначала в методе Terminate будет установлен флаг Terminated (его ты можешь периодически контролировать в теле Execute, и как только увидишь что он True, как можно быстрее завершай работу метода), затем будет вызван метод WaitFor (он дождется завершения работы потока как ОС-объекта) и следом же будет вызван метод Free, который приведет к разрушению потока уже как VCL-объекта


> следом же будет вызван метод Free

не Free, а inherited Destroy предка


evvcom © ( 2005-05-30 16:51 ) [46]

1. Если ты хочешь грохнуть поток сразу по завершении, то проще использовать FreeOnTerminate := True;
2. Если ты собираешься использовать поток повторно, то грохать его не надо сразу. Поэтому вызов Thread.Free должен быть где-то из основного потока. А в Execute даже не выходя из цикла Suspend;
3. В любом случае доп.поток должен как-то сообщить основному, что работу он выполнил. В случае FreeOnTerminate := False; здесь из основного потока и можно вызвать Thread.Free.


Mouserx ( 2005-05-30 16:51 ) [47]


> Digitman © (30.05.05 16:48) [44]

Я имел ввиду не снаружи а освобождение ресурсов, когда поток сам, без стороних «указов», завершит работу. Смотри [41]

destructor TMyThread.Destroy;
begin
inherited; //здесь будут вызваны Terminate, WaitFor и inherited

//здесь поток как ОС-объект уже завершил свою работу
//никто более не обращается ни к fFindedList ни к fIgnoreList
//поэтому именно здесь их можно смело уничтожить


Mouserx ( 2005-05-30 16:55 ) [49]

Ок. Всем большое Спасибо.
Буду щас переваривать и делать как вы мне обьяснили 🙂


Defunct © ( 2005-05-30 17:05 ) [51]

> Mouserx
Обещанный пример, поковыряйте

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

const
WM_FINALIZINGTHREADOBJ = WM_USER + 1;

type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
procedure AcceptThreadData( var MSG: TMessage);message WM_FINALIZINGTHREADOBJ;
end;

type
TMyThread = class(TThread)
private
fList : TStrings;
fOwnerHandle : HWND;
fCanDestroy : boolean;
protected
procedure execute;override;
public
constructor Create(AOwner : HWND);
destructor Destroy;override;
end;

constructor TMyThread.Create;
begin
fOwnerHandle := AOwner;
inherited Create(True);
fList := TStringList.Create;
fCanDestroy := false;
Resume;
end;

procedure TMyThread.execute;
var
i : integer;
begin
i := 0;
while not Terminated and (i


Mouserx ( 2005-05-30 17:12 ) [52]


Defunct © ( 2005-05-30 17:20 ) [53]

Так с авторазрушением

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

const
WM_FINALIZINGTHREADOBJ = WM_USER + 1;

type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
procedure AcceptThreadData( var MSG: TMessage);message WM_FINALIZINGTHREADOBJ;
end;

type
TMyThread = class(TThread)
private
fList : TStrings;
fOwnerHandle : HWND;
fCanDestroy : boolean;
fDestructorPending : Boolean;
protected
procedure execute;override;
public
constructor Create(AOwner : HWND);
destructor Destroy;override;
end;

constructor TMyThread.Create;
begin
fOwnerHandle := AOwner;
inherited Create(True);
fList := TStringList.Create;
FreeOnTerminate := True;
fCanDestroy := false;
fDestructorPending := false;
Resume;
end;

procedure TMyThread.execute;
var
i : integer;
begin
i := 0;
while not Terminated and (i


jack128 © ( 2005-05-30 17:54 ) [54]

Defunct © (30.05.05 16:15) [33]
Но, не находите, это возможно уже ошибка в проектировании, что может привести к серьезным глюкам.

Возможно ошибка в проэктировании.. А возможно и нет..
Это просто первый вариант, который пришел мне в голову..


Mouserx ( 2005-05-30 18:13 ) [55]

Defunct © (30.05.05 17:20) [53]
Пример очень понятен и похож на мой случай.

Но вот что произойдет при одновременном срабатывании Sinchronize со стороны доп. потока и Button2Click со стороны основного потока?
Получится что оба потока будут вечно ждать друг друга?


Mouserx ( 2005-05-30 18:18 ) [56]

Sinchronize в твоем примере нету, но в моем случае имеется. я конечно перед его использованием раньше проверял на if Terminated.


Defunct © ( 2005-05-30 19:48 ) [57]

Mouserx (30.05.05 18:18) [56]

Возможная проблема: после входа в Destructor выполнение метода Synchronize.

Однако эта проблема решается весьма просто: перед вызовом Synchronize проверить переменную fDestructorPending, и не заходить не выполнять Synchronize если DestructorPending.

Ситуация о которой вы говорите невозможна (если не используется Application.ProcessMessages внутри синхронизируемого метода).

синхронизируемый метод и событие Button2Click выполняются последовательно в одном потоке, и если насильно (ProcessMessages) либо как-то еще выполнение синхронизируемого метода не прерывается, то попасть в обработчик Button2Click можно только после завершения работы синхронизируемого метода.


Defunct © ( 2005-05-30 19:54 ) [58]

Defunct © (30.05.05 19:48) [57]

Хотя, возможно придется добавить еще один флаг. Synchronize в вашем случае этот как палка в колесо ;>


Gek1 ( 2005-05-30 20:09 ) [59]


> Однако эта проблема решается весьма просто: перед вызовом
> Synchronize проверить переменную fDestructorPending, и не
> заходить не выполнять Synchronize если DestructorPending

Например ситуация:
Доп. поток (даже проверив перед Synchronize переменную fDestructorPending) «входит» в ожидание синхронизации.
В этот момент основной поток «занят» (гуляет по коду). Гуляя по коду вдруг, например, резко понадобилось аварийно остановить программу. Ясное дело потоки мы тоже пытаемся остановить. Вызывая метод Free дополнительного потока мы натыкаемся на след. конструкцию:
while not fCanDestroy do Sleep(100);

Ну и в результате основной поток ждет пока fCanDestroy не будет true, а доп. поток ничего не может делать. Он сам ждет выполнения кода основного потока через Synchronize.


Gek1 ( 2005-05-30 20:11 ) [60]

Mouserx и Gek1 в данный момент одно и тоже.
(Написал с другого компьютера и не заметил ник)


Defunct © ( 2005-05-30 20:27 ) [61]

Gek1 (30.05.05 20:09) [59]

Это уже другая проблема. И вы прекрасно поняли как все работает, раз углядели такую ситуацию.

Возможно даже, в таком случае (когда точно известно, что поток в настоящее время ожидает возможности выполнить (но еще не приступил к выполнению) метод в основном потоке), насильное разрушение потока в деструкторе TermninateThread будет безболезнено.

PS: Мне очень мешает дать вам правильный совет мое неведенье вашей задачи (вот например, не понимаю зачем в потоке используется Synchronize).


Mouserx ( 2005-05-30 20:51 ) [62]


> Мне очень мешает дать вам правильный совет мое неведенье
> вашей задачи (вот например, не понимаю зачем в потоке используется
> Synchronize).

Через метод Synchronize из доп. потока вызываються public св-ва класса TCharacter.
Думаю вот этот линк даст вам понять чем мы занимаемся:
http://delphimaster.net/view/6-1116426647/

Так вот в доп. потоках «крутится» скриптовый движок Pascal Script и к нему дополнения под данную задачу. Ясное дело я не могу аварийно завершить сам движок, и (в лучшем случае) потерять обьекты, созданные в доп. потоке при выполнении определенной комманды из самого скрипта вместе с самим движком.

В данном случае поток может завершиться сам (например выполниться полностью скрипт) или же (при разных ситуациях) мне надо в деструкторе Destroy класса TCharacter «попросить» потоки завершиться при первой возможности. При этом желательно дождаться пока эти потоки действительно завершаться. Также я еще не продумал как обойти тупиковую ситуацию с Synchronize [59]


Defunct © ( 2005-05-30 21:14 ) [63]

Значится так, потоков много и каждый из них может выполняться в основном.

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

Пишем управляюший класс монитор главного потока, нечто похожее на TCriticalSection из SyncObj, за одним исключением: при нормальной работе при вызове метода Enter увеличивает на 1 внутренний счетчик входов, при вызове Leave уменьшается на 1 внунтренний счетчик. Когда требуется выполнить аварийное завершение потоков, в мониторе главноего потока устанавливаете флаг запрещающий доступ к главному потоку (это будет сопровождаться например так: функция Enter будет возвращать False, а вы в свою очередь в потоках получив значение false не будете запускать метод Synchronize) и периодически проверяете количество входов сопровождая каждую проверку вызовом ProcessMessages. Когда это количество входов равно 0, это значит, ни один из потоков более не ждет обращения к основному потоку, и вы смело можете любой из потоков аварийно завершить как примере [53]. Завершив аварийно какие-то потоки, можете продолжить нормальную работу, сняв флаг запрещающий доступ к главному потоку.


Defunct © ( 2005-05-30 22:30 ) [64]

Если же вы все потоки создаете строго из главного, то есть более простое решение, дорабатываем [53]:

TMyThread = class(TThread)
private
fMainThreadId : Cardinal;
.
end;

constructor TMyThread.Create;
begin
fMainThreadId := GetCurrentThreadId;
fOwnerHandle := AOwner;
.
end;

destructor TMyThread.Destroy;
begin
// На случай если Free вызван из-вне
fDestructorPending := True;
while not fCanDestroy do
begin
Sleep(100);
if fMainThreadId = CurrentThreadid then
Application.ProcessMessages
end;


Mouserx ( 2005-05-31 10:08 ) [65]

Defunct спасибо. С этим понятно.

У меня будет еще вопрос: Как еще можно организовывать двустороний обмен данных между потоками не используя Sinchronize? Стуктура данных в разный момент времени различна.


evvcom © ( 2005-05-31 11:09 ) [66]


> не используя Sinchronize

PostMessage + (возможно) CriticalSection

Источник

Читайте также:  msvcp140d dll что это за ошибка как исправить
Сказочный портал