Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.05.16;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.59 MB
Время: 0.037 c
6-1076827229
Tasadar
2004-02-15 09:40
2004.05.16
SSH и Delphi


11-1069525315
DDA2
2003-11-22 21:21
2004.05.16
Установить дату папке(KOL)


3-1081970454
3APA3A
2004-04-14 23:20
2004.05.16
База не меняет размер...


14-1082639764
Ditrix
2004-04-22 17:16
2004.05.16
Требуется квалифицированный программер


1-1083117685
-=[SDA]=-
2004-04-28 06:01
2004.05.16
Панель в QuickReport!!! -> false!!!





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский