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

Вниз

Как убить объект из его же метода?   Найти похожие ветки 

 
Ega23 ©   (2007-10-12 13:17) [0]

Собственно, сабж.

Есть идея с PostMesage  WM_DESTROY, но возникает вопрос - а если это не "оеонный" класс?


 
Ins ©   (2007-10-12 13:27) [1]


> но возникает вопрос - а если это не "оеонный" класс?

Например так:
1. Посылаем сообщение (WM_USER + 1 хотя бы) PostThreadMessage своему потоку, передавая параметром (например, wParam) Self.
2. В обработчике Application.OnMessage если пришло сообщение WM_USER + 1 вызываем TObject(wParam).Free;

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


 
Ega23 ©   (2007-10-12 13:30) [2]

Интересный вариант.
А если Application нет?


 
Ins ©   (2007-10-12 13:32) [3]

Очень интересный вариант привел DRON здесь:

http://www.delphikingdom.com/asp/answer.asp?IDAnswer=40427


> А если Application нет?

А цикл выборки сообщений есть? Если есть, то внутри его то же самое.


 
Ins ©   (2007-10-12 13:35) [4]

И еще вариант. Заводим специальное message-only окошко, и посылаем PostMessage ообщения ему.


 
Ins ©   (2007-10-12 13:39) [5]

Даже название для класса такого окна вам придумал :) SuicideManagerWindow


 
Slym ©   (2007-10-12 13:41) [6]

Ega23 ©   (12.10.07 13:17)
DelayedFree?
procedure DelayedFree(obj:Pointer);
 function ThreadProc(Aobj: Pointer): Integer;stdcall;
 begin
   TObject(Aobj).Free;
 end;
var FHandle,FThreadID:THandle;
begin
 FHandle:=CreateThread(nil,0,@ThreadProc,Pointer(obj),CREATE_SUSPENDED,FThreadID) ;
 SetThreadPriority(FHandle, THREAD_PRIORITY_IDLE);
 ResumeThread(FHandle);
 CloseHandle(FHandle);
end;


 
Ega23 ©   (2007-10-12 13:42) [7]

Так, с мест сообщают, что Application не будет.


 
Сергей М. ©   (2007-10-12 13:43) [8]


> Ega23 ©   (12.10.07 13:42) [7]


Ну хотя бы один TWinControl-объект будет ?


 
Slym ©   (2007-10-12 13:43) [9]

можно через стандартный TThread и synhronized гасить объект в главном потоке


 
Ins ©   (2007-10-12 13:43) [10]


> Slym ©   (12.10.07 13:41) [6]

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


 
Ins ©   (2007-10-12 13:45) [11]


> Ega23 ©   (12.10.07 13:42) [7]

[4] не подходит? Централизованно и не нужен никакой Application.


 
Ega23 ©   (2007-10-12 13:45) [12]


> Ну хотя бы один TWinControl-объект будет ?


Похоже что нет, это сервис с пайпами


 
Игорь Шевченко ©   (2007-10-12 13:50) [13]

тебе чего надо-то ?


 
palva ©   (2007-10-12 13:51) [14]

А разве обычным образом объект не убивается? Следующая программа печатает один и тот же адрес. То есть второй раз объект создается на месте убиенного.

{$APPTYPE CONSOLE}
uses Classes;
type
 TMyStringList = class(TStringList)
 procedure Dest;
 end;

procedure TMyStringList.Dest;
begin
 Free;
end;

var
 sl: TMyStringList;
begin
 sl := TMyStringList.Create();
 WriteLn(Integer(sl));
 sl.Dest;
 sl := TMyStringList.Create();
 WriteLn(Integer(sl));
 sl.Dest;
end.


 
Ins ©   (2007-10-12 13:56) [15]


> Ega23 ©   (12.10.07 13:45) [12]

Если там нет ни цикла выборки сообщений, ни окна он создавать не может, то сделать так:
1. Просто заносим ссылку на объект в некий список
2. Где-нибудь потом (не в методе какого-либо класса) сканируем этот список и уничтожаем объекты.


 
Ins ©   (2007-10-12 13:57) [16]


> palva ©   (12.10.07 13:51) [14]

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


 
Игорь Шевченко ©   (2007-10-12 13:58) [17]


> Убивается, но делать это в методе своего же класса не рекомендуется,
>  так как код метода после этого продолжает выполняться и
> любое обращение к self скорее всего приведет к исключению.
>


????????????????????


 
Ins ©   (2007-10-12 14:00) [18]


> Игорь Шевченко ©   (12.10.07 13:58) [17]

Что вас удивляет? В своем же методе (сабж вроде как об этом) вызывать Free небезопасно. После этого вызова метод продолжает выполняться, но экземпляра, на который указывает self уже нет.


 
Сергей М. ©   (2007-10-12 14:03) [19]


> сервис с пайпами


Ничто не мешает сервису создавать и испольновать окна.


 
palva ©   (2007-10-12 14:06) [20]

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


 
palva ©   (2007-10-12 14:09) [21]

palva ©   (12.10.07 14:06) [20]
С другой стороны непонятна логика. Если после уничтожения объекта методу нужно обращаться к полям объекта, то зачем тогда уничтожать объект.


 
Ins ©   (2007-10-12 14:09) [22]


> если этот метод не обращается к полям.

Это очень важное если. А если этот метод вызван из другого метода, который потом обращается? А если этот другойвызван из третьего? А если где-то потом еще вызывается виртуальный метод (он же тоже подразумевает обращение к self)? Лучше просто так не делать и тогда жить будет чуточку легче.


 
Ins ©   (2007-10-12 14:11) [23]


> С другой стороны непонятна логика. Если после уничтожения
> объекта методу нужно обращаться к полям объекта, то зачем
> тогда уничтожать объект.

Очень много случаев, когда люди вызывают Sender.Free из обработчика события. А потом удивляются AV или abstract error-у. А ведь нет ничего удивительного. Примеры были (правда на другом форуме), могу привести.


 
Kolan ©   (2007-10-12 14:27) [24]

> 2. Где-нибудь потом (не в методе какого-либо класса) сканируем
> этот список и уничтожаем объекты.

В потоке например, который будет этот список без конца сканить и мочить объекты&#133

Ega,
А может просто сделать интерфейс? Пусть он(объек) сам помрёт когда не нужен будет&#133


 
Игорь Шевченко ©   (2007-10-12 14:29) [25]

Ins ©   (12.10.07 14:00) [18]


> В своем же методе (сабж вроде как об этом) вызывать Free
> небезопасно. После этого вызова метод продолжает выполняться,
>  но экземпляра, на который указывает self уже нет.


???????????????????????????????????????????????????????????

procedure TCustomForm.CMRelease;
begin
 Free;
end;

Вроде безопасно...CMRelease - это факт, СВОЙ метод для объекта TCustomForm


 
Игорь Шевченко ©   (2007-10-12 14:30) [26]


> Это очень важное если. А если этот метод вызван из другого
> метода, который потом обращается? А если этот другойвызван
> из третьего? А если где-то потом еще вызывается виртуальный
> метод (он же тоже подразумевает обращение к self)? Лучше
> просто так не делать и тогда жить будет чуточку легче.


Совсем легко станет если учить матчасть. (Уж извини)


 
Ins ©   (2007-10-12 14:31) [27]


> В потоке например, который будет этот список без конца сканить
> и мочить объекты…

Не понимает народ.. На мультипроцессорной системе этот поток может выполняться одновременно с главным и замочить объект в то время, пока главный с ним работает. В этом случае нет принципиальной разницы с простым вызовом Free из своего же метода. Такой поток придется синхронизировать с главным. Чтобы главный в это время уже закончил работать с объектом. А раз так, то зачем еще один поток, сделаем в главном, только при завершении работы с объектом. Веди наверняка главный поток вертиться в каком-либо цикле, вот в конце цикла и анализировать список и убивать объекты. Вполне безопасно.


 
Ins ©   (2007-10-12 14:40) [28]


> Вроде безопасно...CMRelease - это факт, СВОЙ метод для объекта
> TCustomForm

Безопасно? Ну пошлите это сообщение (CM_RELEASE) через SendMessage или Perform где-то из глубины кода метода, который потом еще что-то делает с self-ом. Посмотрим :) Вот даже пример:

procedure TForm1.Button1Click(Sender: TObject);
begin
 Perform(CM_RELEASE,0,0);
 Caption:="123";
end;


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


 
Ins ©   (2007-10-12 14:46) [29]


> Вроде безопасно...

Только при соблюдении ряда условий, которые Borland сами для нас соблюли (см метод Release).


 
Leonid Troyanovsky ©   (2007-10-12 14:49) [30]


> Игорь Шевченко ©   (12.10.07 14:29) [25]

> Вроде безопасно...

Особенно забавно в главной форме:

procedure TForm1.Button1Click(Sender: TObject);
begin
 Release;
 ShowMessage("The end");
end;

т.е., приложение продолжит жить бесформенно.

--
Regards, LVT.


 
Игорь Шевченко ©   (2007-10-12 14:58) [31]

Ins ©   (12.10.07 14:40) [28]
Leonid Troyanovsky ©   (12.10.07 14:49) [30]

Если в коде написать:

Foo.Free
Foo.Bar := smth

И получится ошибка, вас это не удивит ? :)


 
palva ©   (2007-10-12 14:59) [32]

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


 
Ins ©   (2007-10-12 15:03) [33]


> И получится ошибка, вас это не удивит ? :)

Не удивит. Меня удивляет лишь то, что вы тоже самое и предлагаете сделать, и говорите, что это вполне себе безопасно. :) Хотя, хозяин-барин, просто когда вы, или тот, кому вы посоветуете так сделать, не обговорив все "но", разобьет себе лоб - не удивляйтесь.


 
Ins ©   (2007-10-12 15:06) [34]


> Как убить, если убивать нельзя.

Можно, даже варианты предложены. :) В большинсвте своем они подобны методу Release - посылка асинхронного сообщения. Только разница в том кому посылать. Если самому себе (правда нужно чтобы объект был оконным), то нужно соблюсти правило "необращения к Self после Free".


 
palva ©   (2007-10-12 15:07) [35]

Ну а кто говорит, что это безопасно. Здесь лишь говорят, что никакой разницы в убивании объекта из метода или не из метода нет. Убить можно и так, и так, но только потом помнить, что объект убит и не пользоваться его полями.


 
Игорь Шевченко ©   (2007-10-12 15:10) [36]

Ins ©   (12.10.07 15:06) [34]

Я к тому, что твой и Леонида примеры по сути аналогичны моему с заведомым удалением объекта.
Но никто же при этом не утверждает, что вызов Free небезопасен, нес па ?


 
palva ©   (2007-10-12 15:12) [37]

> Можно, даже варианты предложены.
Ну это уже не из метода будет. Автор хочет из метода. И у него нет никаких препятствий (кроме заповеди "не убий") это сделать. Небезопасно - это возможно. Но настолько же небезопасно, как в основной программе уничтожить объект и сразу же им воспользоваться.


 
Leonid Troyanovsky ©   (2007-10-12 15:13) [38]


> Игорь Шевченко ©   (12.10.07 14:58) [31]

> И получится ошибка, вас это не удивит ? :)

А я и не делал ничего подобного Foo.Bar := smth.

Более того, в хелпе обещали, что Release сработает
после выхода из обработчика (какая самонадеянность)

--
Regards, LVT.


 
Ins ©   (2007-10-12 15:20) [39]


> palva ©   (12.10.07 15:12) [37]

Просто можно сделать безопасно. Сделав это не из метода своего класса. Иначе - небезопасно, так как метод продолжает выполняться с невалидным self. Повезет-неповезет, зависит от того, как это реализует программист. Задумается ли он о многих не очень очевидных вещах (в частности, что не только к полям нельзя обращаться, но и к виртуальным методам). И от того, откуда этот метод вызван. Если из другого метода, то теперь ответственность на том другом методе.


 
oxffff ©   (2007-10-12 15:26) [40]

Можно убивать по разному, главное чтобы убить. А как это без разницы.



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

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

Наверх




Память: 0.57 MB
Время: 0.022 c
2-1192502547
npr2
2007-10-16 06:42
2007.11.11
dbgrid


15-1190992526
vasIZmax
2007-09-28 19:15
2007.11.11
True, False и Почти (Almost, по англ. по-моему))))


2-1192950817
2pac
2007-10-21 11:13
2007.11.11
CreateWindowEx - первый и четвертый параметры


8-1168776768
andr1962
2007-01-14 15:12
2007.11.11
Помогите с directdraw


2-1192895025
StanislavLZ
2007-10-20 19:43
2007.11.11
Два вопроса по TMemo