Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.05.16;
Скачать: CL | DM;

Вниз

Как узнать о существовании объекта?   Найти похожие ветки 

 
w666w   (2004-04-26 16:23) [0]

Уважаемые мастера, подскажите пожалуйста, каким образом решить след. проблему:

Существует объект
 TMyObject = class(TObject)
 ...
 end;

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

В приложении есть дополнительные потоки, которые имеют ссылки на этот объект fMyObject : TMyObject (передаются в конструкторе, допустим). Потоки работаю длятельное время, т.е. не отмерают моментально. В потоках, перед использованием этого объекта, необходимо проверить его существование, иначе вылетает Access Violation (это естественно). Объект единственный, потоков его использующих - много.

Например Assigned(fMyObject) всегда возвращает true, даже если объект давно уничтожен.

Как это сделать наиболее просто икорректно?

Большое спасибо.


 
Тимохов ©   (2004-04-26 16:26) [1]


> наиболее просто икорректно

var
  o: tobject;
begin
  o := fmyobject;
  fmyobject := nil;
  o.free();
end;
при этом при обращении к fmyobject из потоков проверять, что <> nil.

я бы сделал так.


 
w666w   (2004-04-26 16:27) [2]

if fMyObject.InstanceSize > 0 тоже не работает, хотя честно говоря, я не уверен, что этим InstanceSize можно вообще пользоваться...


 
w666w   (2004-04-26 16:31) [3]

> Тимохов

И каким образом потоки узнают, что их fmyobject тоже nil?


 
Тимохов ©   (2004-04-26 16:32) [4]


> if fMyObject.InstanceSize > 0 тоже не работает, хотя честно
> говоря, я не уверен, что этим InstanceSize можно вообще
> пользоваться...

не уверен, не пользуйся.


> И каким образом потоки узнают, что их fmyobject тоже nil?

что значит их fmyobject? Бывает еще не их? Подробнее можно, что вы имеете в виду.


 
Тимохов ©   (2004-04-26 16:38) [5]

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

у вас объект один на все потоки?
если да, то используйте одну глобальную переменную glMyObject и из всех потоков обращайтесь к ней.


 
Palladin ©   (2004-04-26 16:39) [6]

а может вообще не стоит его освобождать?


 
Тимохов ©   (2004-04-26 16:41) [7]


> glMyObject и из всех потоков обращайтесь к ней.

с учетом кода
var
  o: tobject;
begin
  o := glmyobject; // glmyobject - глобальная переменная
  glmyobject := nil;
  o.free();
end;

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

Если же у вас у каждого потока свой экземпляр TMyObject и в другом потоке этот экземпляр может быть удален, то нужно просто явно ставить значение fMyObject равным nil при удалении объекта.
И опять же при обращении к  fMyObject проверять, то она не равна nil.


 
w666w   (2004-04-26 16:54) [8]

>Palladin
Я понимаю, что существует множество способов реализовать работу по другому, но все же есть необходимость сделать именно так.

> Тимохов
Именно это решение мне и приходило в голову, но я не смог реализовать этого (честно говоря уже не помню почему). Вот на скорую руку собрал рабочий пример:

unit Unit1;

interface

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

type
 TMyObject = class(TObject)
 private
   fName : string;
 public
   property Name : string read fName write fName;
 end;

 TMyThread = class(TThread)
 private
   fMyObject : TMyObject;
   fMyText : string;
   procedure ChangeMemo;
 public
   constructor Create(aSuspended : boolean; aMyObject : TMyObject);
   procedure Execute; override;
 end;

 TForm1 = class(TForm)
   Button1: TButton;
   Button2: TButton;
   Button3: TButton;
   Memo1: TMemo;
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
   procedure Button3Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;
 fMyObject : TMyObject;

implementation

{$R *.dfm}

procedure TMyThread.ChangeMemo;
begin
 Form1.Memo1.Lines.Add(fMyText);
end;

constructor TMyThread.Create(aSuspended : boolean; aMyObject : TMyObject);
begin
 inherited Create(aSuspended);
 fMyObject := aMyObject;
end;

procedure TMyThread.Execute;
begin
 if Assigned(fMyObject) then
   fMyText := "Thread #" + IntToStr(ThreadID) + "started. Object is alive and have name: " + fMyObject.Name
 else
   fMyText := "Thread #" + IntToStr(ThreadID) + "started. Object is dead";
 Synchronize(ChangeMemo);

 Sleep(random(10000)); // &#232;&#236;&#236;&#232;&#242;&#232;&#240;&#243;&#229;&#236; &#240;&#224;&#225;&#238;&#242;&#243; &#239;&#238;&#242;&#238;&#234;&#224;, &#231;&#224;&#236;&#232;&#237;&#224;&#254;&#249;&#243;&#254; &#237;&#229;&#232;&#231;&#226;&#229;&#241;&#242;&#237;&#238;&#229; &#226;&#240;&#229;&#236;&#255;

 if Assigned(fMyObject) then
   fMyText := "Thread #" + IntToStr(ThreadID) + "finished. Object is alive and have name: " + fMyObject.Name
 else
   fMyText := "Thread #" + IntToStr(ThreadID) + "finished. Object is dead";
 Synchronize(ChangeMemo);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 fMyObject := TMyObject.Create;
 fMyObject.Name := "&#200;&#236;&#255; &#238;&#225;&#250;&#229;&#234;&#242;&#224;";
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 fMyObject.Free;
end;

procedure TForm1.Button3Click(Sender: TObject);
var i : integer;
begin
 for i := 0 to 10 do begin
   TMyThread.Create(false, fMyObject);
 end;
end;

end.

Попробуйте после запуска потоков (но когда несколько еще живы), уничтожить объект. Вот в этом и суть проблемы.

Не могли бы Вы дать пример рабочего кода?


 
Гаврила   (2004-04-26 16:54) [9]

А что вы собираетесь делать в случае если объект уже уничтожен ?
Странная логика какая-то


 
evvcom ©   (2004-04-26 16:55) [10]


> можно не использовать никаких средств синхронизации

нельзя не использовать! Пример.
В доп. потоке делается проверка

if Assigned(glmyobject) then // glmyobject <> nil

теперь переключение на осн. поток. Делается

 glmyobject := nil;
 o.free();

теперь переключение на доп.поток, условие уже проверено, получили истину
 glmyobject.SomeMethodOrProp // Получаем AV

Использование простейших критических секций эту проблему убирают.


 
Тимохов ©   (2004-04-26 17:02) [11]


> evvcom ©   (26.04.04 16:55) [10]

Полностью согласен. Про возможную ошибку при вроверке забыл :((

Автору.
Слушайте [10].
Синхронизацию делать надо.


 
w666w   (2004-04-26 17:02) [12]

> evvcom
Именно эта проблема и возникает! На самом деле код намного сложнее, чем приведенный мной пример, но суть та же.

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


 
Тимохов ©   (2004-04-26 17:08) [13]


> TMyThread.Create(false, fMyObject);

так делать нельзя.
Если suspended = false, то нельзя менять никакие private свойства класса, которые используются в execute.
надо
create(true,...)
fMyObject := ...
Resume;


> procedure TForm1.Button2Click(Sender: TObject);
> begin
>  fMyObject.Free;
> end;

сделайте fMyObject глобальной для модуля (под implementation)
т.е. не передавайте ее в конструктор. И вообще уберите fMyObject и описания потока.
// В потоке
EnterCriticalSection(fcs);
try
  if Assigned(fMyObject) then ... делайте свои дела
finally
  LeaveCriticalSection(fcs);
end;
// В главном потоке
EnterCriticalSection(fcs);
try
  fMyObject.free();
  fMyObject := nil;
finally
  LeaveCriticalSection(fcs);
end;

где
fcs: TRTLCriticalSection;
инициализаия InitializeCriticalSection(fcs);
удаление крит секции DeleteCriticalSection(fcs);
это описано где-то под implementaion.

в общем-то все.


 
w666w   (2004-04-26 17:48) [14]

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

unit Unit1;

interface

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

const
 REMOVE_MY_COLLECTION_ITEM = WM_USER + 1;
 MAXIMUM_ITEM_ERRORS = 5;

type
 TMyCollectionObject = class(TCollectionItem)
 private
   fName : string;
   fErrors : integer;
 public
   constructor Create(aCollection: TCollection); override;
   property Name : string read fName write fName;
   property Errors : integer read fErrors write fErrors;
 end;

 TMyCollection = class(TCollection)
 public
   function Add(aName : string) : TMyCollectionObject;
   function GetItem(aIndex : integer) : TMyCollectionObject;
   procedure SetItem(aIndex : integer; aValue : TMyCollectionObject);
   property Items[aIndex: integer]: TMyCollectionObject read GetItem write SetItem; default;
 end;

 TMyThread = class(TThread)
 private
   fMyObject : TMyCollectionObject;
   fMyText : string;
   procedure ChangeMemo;
 public
   constructor Create(aSuspended : boolean; aMyObject : TMyCollectionObject);
   procedure Execute; override;
 end;

 TForm1 = class(TForm)
   Memo1: TMemo;
   Button1: TButton;
   procedure FormCreate(Sender: TObject);
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
   procedure Button1Click(Sender: TObject);
 private
   procedure OnRemoveItem(var Msg: TMessage); message REMOVE_MY_COLLECTION_ITEM;
 end;

var
 Form1: TForm1;
 fMyCollection : TMyCollection;
implementation

{$R *.dfm}

procedure TMyThread.ChangeMemo;
begin
 Form1.Memo1.Lines.Add(fMyText);
end;

constructor TMyThread.Create(aSuspended : boolean; aMyObject : TMyCollectionObject);
begin
 inherited Create(aSuspended);
 fMyObject := aMyObject;
end;

procedure TMyThread.Execute;
begin
 if Assigned(fMyObject) then
   fMyText := "Thread #" + IntToStr(ThreadID) + "started. Object " + fMyObject.Name + " is alive and have errors: " + IntToStr(fMyObject.Errors)
 else
   fMyText := "Thread #" + IntToStr(ThreadID) + "started. Object is dead";
 Synchronize(ChangeMemo);

 Sleep(random(10000)); // иммитируем работу потока, заминающую неизвестное время

 if Assigned(fMyObject) then begin
   fMyObject.Errors := fMyObject.Errors + 1; // допустим, что ошибка всегда
   fMyText := "Thread #" + IntToStr(ThreadID) + "started. Object " + fMyObject.Name + " is alive and have errors: " + IntToStr(fMyObject.Errors);
   if fMyObject.Errors >= MAXIMUM_ITEM_ERRORS then // как остальным потокам узнать, что этот объект ужу удален????
     SendMessage(Application.MainForm.Handle, REMOVE_MY_COLLECTION_ITEM, Integer(@fMyObject), 0); // AV если fMyObject уже не существует
 end else begin
   fMyText := "Thread #" + IntToStr(ThreadID) + "finished. Object is dead";
 end;
 Synchronize(ChangeMemo);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 fMyCollection := TMyCollection.Create(TMyCollectionObject);
 fMyCollection.Add("Имя Объекта - " + IntToStr(Random(10000000)));
 fMyCollection.Add("Имя Объекта - " + IntToStr(Random(10000000)));
 fMyCollection.Add("Имя Объекта - " + IntToStr(Random(10000000)));
 fMyCollection.Add("Имя Объекта - " + IntToStr(Random(10000000)));
 fMyCollection.Add("Имя Объекта - " + IntToStr(Random(10000000)));
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 fMyCollection.Free;
end;

constructor TMyCollectionObject.Create(aCollection: TCollection);
begin
 inherited;
 Errors := 0;
end;

function TMyCollection.Add(aName: string): TMyCollectionObject;
var fItem : TMyCollectionObject;
begin
 fItem := TMyCollectionObject(inherited Add);
 fItem.fName := aName;
 Result := fItem;
end;

function TMyCollection.GetItem(aIndex: integer): TMyCollectionObject;
begin
 Result := TMyCollectionObject(inherited Items[aIndex]);
end;

procedure TMyCollection.SetItem(aIndex: integer;
 aValue: TMyCollectionObject);
begin
 Items[aIndex].Assign(aValue);
end;

procedure TForm1.OnRemoveItem(var Msg: TMessage);
var fItem : TMyCollectionObject;
begin
 if (Msg.WParam <= 0) then begin
   exit;
 end;
 try
   fItem := TMyCollectionObject(Pointer(Msg.WParam)^);
   fItem.Free;
 except
   exit;
 end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var i : integer;
begin
 for i := 0 to 10 do begin
   TMyThread.Create(false, fMyCollection.Items[Random(fMyCollection.Count)]); // Random - для того, чтобы несколько потоков имело ссылку на 1 объект
 end;
end;

end.


 
Тимохов ©   (2004-04-26 18:11) [15]

вы упрямы и ленивы, и не хотите поправить явные ошибки, на которые я вам указал - почему у вас av, я вам указал (подсказка -asuspended, объект у вас не уже не существует, а еще не существует)


 
w666w   (2004-04-26 18:12) [16]

Весь приведенный выше код создан только для того, чтобы дать возможность четко увидеть момент, в который необходимо узнать о РЕАЛЬНОИ существовании объекта. А происходит это именно в execute потока в первой строке кода

 if Assigned(fMyObject) then begin
   fMyObject.Errors := fMyObject.Errors + 1; // допустим, что ошибка всегда
   fMyText := "Thread #" + IntToStr(ThreadID) + "started. Object " + fMyObject.Name + " is alive and have errors: " + IntToStr(fMyObject.Errors);
   if fMyObject.Errors >= MAXIMUM_ITEM_ERRORS then // как остальным потокам узнать, что этот объект ужу удален????
     SendMessage(Application.MainForm.Handle, REMOVE_MY_COLLECTION_ITEM, Integer(@fMyObject), 0); // AV если fMyObject уже не существует
 end else begin
   fMyText := "Thread #" + IntToStr(ThreadID) + "finished. Object is dead";
 end;

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

if Assigned(fMyObject)

будет всегда возвращать true. Что, собственно и есть суть всего топика - "Как узнать о существовании объекта?". Помогите.


 
w666w   (2004-04-26 18:17) [17]

> Тимохов
В последнем примере я исправил ситуацию с aSuspended - я не меняю свойства потока после его запуска.

"объект у вас не уже не существует, а еще не существует"
- неверно, так как ошибка возникает ТОЛЬКО в блоке после

Sleep(random(10000)); // иммитируем работу потока, заминающую неизвестное время

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


 
WebErr ©   (2004-04-26 18:21) [18]

Удалено модератором


 
Тимохов ©   (2004-04-26 18:35) [19]


> w666w   (26.04.04 18:17) [17]

На самом деле у вас какая-то странная задача.
Palladin заметил, что может вам не надо удалять объекты? Прислушайтесь к нему.
Сделайте так:
1. Есть объект обертка, который содержит ваш объект TMyCollectionObject (т.е.
TWrapper = class
  fMCO: TMyCollectionObject
  ...
end;
)
2. ВЫ создаете wrapper для каждого TMyCollectionObject
3. В поток передаете именно wrapper.
4. Уничтожаете не wrapper, а fMCO через метод TWrapper (например
procedure TWrapper.Clear;
begin
  fMCO.Free;
  fMCO := nil;
end;
)
5. Т.к. wrapper всегда жив, то всегда можно понять жив ли соответствующий TMyCollectionObject.

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


 
panov ©   (2004-04-26 19:07) [20]

Возможно поможет вот это
type
TMyCollectionObject = class(TCollectionItem)
private
  CS: RTLCriticalSection;
  fName : string;
  fErrors : integer;
public
  constructor Create(aCollection: TCollection); override;
  property Name : string read fName write fName;
  property Errors : integer read fErrors write fErrors;
end;

В конструкторе создаем секцию, в деструкторе уничтожаем, естественно.

function TMyCollection.Add(aName: string): TMyCollectionObject;
var fItem : TMyCollectionObject;
begin
fItem := TMyCollectionObject(inherited Add);
fItem.fName := aName;
Result := fItem;
end;

function TMyCollection.GetItem(aIndex: integer): TMyCollectionObject;
begin
EnterCriticalSection(CS);
Result := TMyCollectionObject(inherited Items[aIndex]);
LeaveCriticalSection(CS);
end;

procedure TMyCollection.SetItem(aIndex: integer;
aValue: TMyCollectionObject);
begin
EnterCriticalSection(CS);
Items[aIndex].Assign(aValue);
LeaveCriticalSection(CS);
end;

А вот это использование windows-сообщений непонятно для чего здесь.

procedure TForm1.OnRemoveItem(var Msg: TMessage);
begin
EnterCriticalSection(CS);
if (Msg.WParam <= 0) then begin
  exit;
end;
try
  TMyCollectionObject(Pointer(Msg.WParam)^).Free;
  TMyCollectionObject(Pointer(Msg.WParam)^) := nil;

except
  exit;
end;
LeaveCriticalSection(CS);
end;


 
Тимохов ©   (2004-04-26 19:30) [21]


> panov ©   (26.04.04 19:07) [20]

Не поможет это ему.
Автору нужно, чтобы все потоки, которые ссылаются на объект узнали о том, что объект удален.
Вообще говоря, это точно можно сделать через сообщения: объект посылает сообещиния всем потокам, которые на него (объект) ссылаются. Можно не сообщения, а просто очищать ссылку на объект. Но в обоих случаях объект должен узанавать, какие потоки на него ссылаются.


 
panov ©   (2004-04-26 19:30) [22]

Что касается первого(упрощенного) примера:

unit Unit1;

interface

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

type
PMyObject = ^TMyObject;
TMyObject = class(TObject)
 private
   fName : string;
 public
   property Name : string read fName write fName;
 end;

 TMyThread = class(TThread)
 private
   fMyObject : PMyObject;
   fMyText : string;
   procedure ChangeMemo;
 public
   constructor Create(aSuspended : boolean; aMyObject : PMyObject);
   procedure Execute; override;
 end;

 TForm1 = class(TForm)
   Button1: TButton;
   Memo1: TMemo;
   Button2: TButton;
   Button3: TButton;
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
   procedure Button3Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;
 fMyObject : TMyObject;
implementation

{$R *.dfm}

procedure TMyThread.ChangeMemo;
begin
Form1.Memo1.Lines.Add(fMyText);
end;

constructor TMyThread.Create(aSuspended : boolean; aMyObject : PMyObject);
begin
inherited Create(True);
fMyObject := aMyObject;
Resume;
end;

procedure TMyThread.Execute;
begin
if Assigned(fMyObject^) then
  fMyText := "Thread #" + IntToStr(ThreadID) + "started. Object is alive and have name: " + fMyObject.Name
else
  fMyText := "Thread #" + IntToStr(ThreadID) + "started. Object is dead";
Synchronize(ChangeMemo);

Sleep(random(10000)); // eiieoe?oai ?aaioo iioiea, caieia?uo? iaecaanoiia a?aiy

if Assigned(fMyObject^) then
  fMyText := "Thread #" + IntToStr(ThreadID) + "finished. Object is alive and have name: " + fMyObject.Name
else
  fMyText := "Thread #" + IntToStr(ThreadID) + "finished. Object is dead";
Synchronize(ChangeMemo);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
fMyObject := TMyObject.Create;
fMyObject.Name := "??? ???????";
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
fMyObject.Free;
fMyObject := nil;
end;

procedure TForm1.Button3Click(Sender: TObject);
var
 i : integer;
begin
for i := 0 to 10 do begin
  TMyThread.Create(false, @fMyObject);
end;
end;
end.


 
Тимохов ©   (2004-04-26 19:33) [23]


> panov ©   (26.04.04 19:30) [22]

Да автор уже сказал, что это слишком упрошенный пример, который не удовлетворяет его. В данном пример объект всего один fMyObject и танцы с suspended/resume его не спасут.

Автору.
Странная все же у вас задача...
Подумайте хорошенько - может все таки здесь что-то не то?


 
panov ©   (2004-04-26 19:36) [24]

>Тимохов ©   (26.04.04 19:33) [23]

Если автору надо это, то решением может быть передача указателя на объекты по ссылке. Это решает проблемы, но усложняет код.


 
Тимохов ©   (2004-04-26 19:43) [25]


> panov ©   (26.04.04 19:36) [24]

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


 
w666w   (2004-04-26 19:52) [26]

Очень хотелось бы услышать подробнее о "передача указателя на объекты по ссылке", так как этот вариант крутился в голове. Но я никак не могу реализовать этот подход. Спасибо.


 
panov ©   (2004-04-26 20:40) [27]

>w666w   (26.04.04 19:52) [26]

Погорячился я... нельзя так делать.


 
Игорь Шевченко ©   (2004-04-26 22:04) [28]


> который может быть уничтожен в любой момент выполнения приложения,
> допустим, по нажатию кнопки.
>
> В приложении есть дополнительные потоки, которые имеют ссылки
> на этот объект fMyObject : TMyObject (передаются в конструкторе,
> допустим). Потоки работаю длятельное время, т.е. не отмерают
> моментально. В потоках, перед использованием этого объекта,
> необходимо проверить его существование, иначе вылетает Access
> Violation (это естественно). Объект единственный, потоков
> его использующих - много.


Как бы я сделал - просто и тупо. Завел бы дополнительную переменную типа Boolean, означающую, живой объект или нет. В конструкторе объекта установил ее в true, в деструкторе в false. Соответсвенно, каждый поток должен бы был проверять эту переменную, прежде чем использовать ссылку на объект, если переменная равна false, то сслыка на объект недействительна и ее следует обнулить или предпринять еще какие-то действия.
Разумеется, я исхожу из предположения, что потоки имеют свои личные переменные, указывающие на этот единственный объект.
Можно конечно вести счетчик ссылок на объект, и уничтожать его только после того, как все ссылки на него пропадут, но, IMHO, это усложнение.


 
Тимохов ©   (2004-04-27 11:10) [29]


> , указывающие на этот единственный объект.

да у автора в том то и дело, что объект не единственный

объектов несколько, потоков несколько, на один объект могу ссылать несколько потоков.


 
Игорь Шевченко ©   (2004-04-27 11:45) [30]


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


Я вроде автора процитировал ?


 
evvcom ©   (2004-04-27 14:19) [31]

Много всего путанного написано.


> Если автору надо это, то решением может быть передача указателя
> на объекты по ссылке. Это решает проблемы, но усложняет
> код.


> Погорячился я... нельзя так делать.


Почему нельзя? И почему усложняет код? Чтобы не извещать потоки, передать им указатель, и пусть они сами проверяют есть объект или нет, но любое обращение к объекту делать через критические секции!

> Очень хотелось бы услышать подробнее о "передача указателя
> на объекты по ссылке",

Только что заметил, что в panov ©   (26.04.04 19:30) [22] - так и сделано.


 
Тимохов ©   (2004-04-27 14:24) [32]


> Игорь Шевченко ©   (27.04.04 11:45) [30]

Наверное.
Запустался я что-то в этом топике - автор сильно постарался :)))
Автор сначала писал одно (объект де один), а затем привел пример в котором объектов много.

Я вам возразил, т.к. по результатам общения с автором понял, что он имеет в виду не то, что сказал вначале.
Вот.


 
panov ©   (2004-04-27 14:42) [33]

>evvcom ©   (27.04.04 14:19) [31]

...пусть они сами проверяют есть объект или нет...

Можно небольшой кусочек кода для иллюстрации...


 
Игорь Шевченко ©   (2004-04-27 14:43) [34]


> Я вам возразил, т.к. по результатам общения с автором понял,
> что он имеет в виду не то, что сказал вначале.


У меня телепатия не так сильно развита :)

Для множества объектов тоже можно способ придумать, но давайте дождемся автора.


 
evvcom ©   (2004-04-27 15:08) [35]

2 panov ©   (27.04.04 14:42) [33]:
Вы же сами написали в [22] такой код:

procedure TMyThread.Execute;
begin
if Assigned(fMyObject^) then
 fMyText := "Thread #" + IntToStr(ThreadID) + "started. Object is alive and have name: " + fMyObject.Name
else
 fMyText := "Thread #" + IntToStr(ThreadID) + "started. Object is dead";

где fMyObject: PMyObject; - указатель на объект
Но здесь один недостаток, проверку и использование надо заключить в критическую секцию!
EnterCriticalSection(...);
if Assigned(fMyObject^) then
 fMyObject^...
LeaveCriticalSection(...);


 
panov ©   (2004-04-27 15:12) [36]

>evvcom ©   (27.04.04 15:08) [35]

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

Вопрос - зачем?

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


 
evvcom ©   (2004-04-27 16:01) [37]


> В данном случае коллизий не может быть никаких и нет необходимости
> в использоании критических секий.

Ну как же? Вы же в Button2Click в осн. потоке удаляете объект, а из доп. потока к нему обращаетесь. Кроме того Вы по Button1Click создаете объект(ы), не задумываясь о том, что он(и) уже существует(ют), а в Button2Click удаляете только последний созданный. Здесь надо это все как-то запоминать и использовать, например в динамическом массиве.



Страницы: 1 вся ветка

Текущий архив: 2004.05.16;
Скачать: CL | DM;

Наверх




Память: 0.6 MB
Время: 0.027 c
6-1080573842
Stren___
2004-03-29 19:24
2004.05.16
TNMPOP3


14-1083009008
Yanis
2004-04-26 23:50
2004.05.16
Отгадай


14-1082681741
alexandri
2004-04-23 04:55
2004.05.16
Такие вот дела ....


14-1083042907
Drozdov A
2004-04-27 09:15
2004.05.16
CorelDraw 11


14-1082552866
Сергей Волкович
2004-04-21 17:07
2004.05.16
Ищем сотрудников