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

Вниз

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

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

Наверх





Память: 0.56 MB
Время: 0.044 c
15-1191866338
DeadLord
2007-10-08 21:58
2007.11.11
странное поведение StringGrid


2-1192546016
Кевларвестов Семен
2007-10-16 18:46
2007.11.11
Конвертировани строки 01.01.0 в дату


2-1192770109
031178
2007-10-19 09:01
2007.11.11
TTreeView


2-1192521779
Ega23
2007-10-16 12:02
2007.11.11
Как поменять дату файла?


2-1192272904
apic
2007-10-13 14:55
2007.11.11
Права пользователя





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский