Форум: "Начинающим";
Текущий архив: 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. Где-нибудь потом (не в методе какого-либо класса) сканируем
> этот список и уничтожаем объекты.
В потоке например, который будет этот список без конца сканить и мочить объекты…
Ega,
А может просто сделать интерфейс? Пусть он(объек) сам помрёт когда не нужен будет…
← →
Игорь Шевченко © (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.55 MB
Время: 0.08 c