Форум: "Основная";
Текущий архив: 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)); // èììèòèðóåì ðàáîòó ïîòîêà, çàìèíàþùóþ íåèçâåñòíîå âðåìÿ
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;
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.038 c