![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Выяснение причины сообщения "A component named . already exists" [D6]
Димон © (2005-03-01 12:02:00)Есть примерно такой код, который выполняется в одном из методов другой формы:
kForm := TMyForm.Create(Application);
try
Result := kForm.ShowModal = mrOk;
if Result then
kForm.SaveResults(ResultObject);
finally
kForm.Release();
end;
После этого кода результаты диАлогового ввода пользователя, сохраненные командой SaveResults в ResultObject, неким образом обрабатываются.
Бывают случае когда обработка заканчивается с ошибкой. После этого в пириведенном выше коде возбуждается исключение указанное в сабже.
Вопрос: что приводит к такой ошибке?
Проде бы TComponent должен сам заботиться о выборе имени дабы избежать конфликта имен в рамках своего owner. С чем может быть связано отсутствие такого подбора в моем случае?
KSergey (2005-03-01 13:49:00) [21]> [19] Димон (01.03.05 13:45)
> Потому и спрашиваю.
Внимательно вдумайтесь в термин ЮЗ "внутренние компоненты".
Признаюсь, я не сразу въехал, как только понял -все стало ясно.
PS
Если уж так нужна подсказка: в вашем примере [5] форма - явно пустая. А можеи и не в этом дело... (к ЮЗ: но ведь я могу создать 2 экземпляра одной и той же формы! Любой!)
Димон (2005-03-01 13:46:00) [22]
> Привет
пример :)
Димон (2005-03-01 13:45:00) [23]
> [18] Юрий Зотов © (01.03.05 13:03)
Привет с внутренними компонентами неприминим - т.к. внутренние компоненты я не создаю. Это раз.
> [16] KSergey © (01.03.05 12:56)
Мой пример очень даже убедителен. Для форм нет необъходимости задавать уникальные имена.
Мне не сложно - я очищаю имя. Это не проблема. Конечно же все работает.
Проблема в том, что я не понимаю такое поведение - если имя не уникально, то ошибки нет, но только в том случае, если раньше не было где-то как-то возникшего исключения. Знал бы где! Такое ощущение, что механизм выделения имен нарушается. Как? Фиг его знает. Потому и спрашиваю.
Юрий Зотов (2005-03-01 13:03:00) [24]> Димон (01.03.05 12:44) [13]
> Ну допустим я пытаюсь второй раз открыть ту же форму.
> Ну и что?
Не открыть, а загрузить. И при чтении из DFM первого же внутреннего компонента формы выясняется, что компонент с таким именем на этой форме уже есть. И приплыли.
Скорее всего, причина именно в этом.
> Пример из [5] показывает...
См. [14]. Для внутренних компонентов пример из [5] неприменим.
clickmaker (2005-03-01 13:00:00) [25]
> Димон (01.03.05 12:44) [13]
а тебе так принципиально это release? Делай просто Free
KSergey (2005-03-01 12:56:00) [26]> [14] Юрий Зотов © (01.03.05 12:53)
> имена внутренних компонентов жестко прописаны в DFM
Блин, точно! Он же не просто объект создает, а форму... Туплю...
К стати, именно в Release тут может и быть косяк: если объект таки успеет разрушиться - то ошибки нет, если не успевает - ошибка. Выкинуть. Глупость это здесь полная.
KSergey (2005-03-01 12:54:00) [27]> [13] Димон (01.03.05 12:44)
> должно сгенериться
> новое уникальное имя.
Вам тут уже сказали не раз: НЕ ДОЛЖНО!! Не должно - и все тут!
И никакой ваш пример тут не убедителен, я сам на это не раз натыкался (к стати, может форма и генерит новое имя верно, но в ней ли дело? Что у вас там создается - хрен знает. Может и не в ней дело.
Теперь еще. После вызова Release, как вы знаете, сразу объект не уничтожается. В этом может быть как раз и косяк.
Я взял за правило динамически создаваемым объектам давать имя - пустую строку. Тогда никто никогда не ругается.
Опять же в этом коде просто НЕТ СМЫСЛА в Release. Это излишняя нагрузка на систему, не более.
Юрий Зотов (2005-03-01 12:53:00) [28]> Димон (01.03.05 12:22) [8]
> Тода как объяснить работоспособность моего кода из [5]?
Ответ лежит в модуле Classes:
function TReader.ReadRootComponent(Root: TComponent): TComponent;
function FindUniqueName(const Name: string): string;
Вот эта самая FindUniqueName и формирует суффикс "_цифра". Но работает все это только для глобальных компонентов, а имена внутренних компонентов жестко прописаны в DFM и грузятся оттуда без всякой модификации (ведь иначе будет невозможно проинициализировать соответствующие поля контейнера).
В любом случае видим, что сам компонент о выборе своего имени не заботится. Он только проверяет его в SetName.
Димон (2005-03-01 12:44:00) [29]Понимаешь, в чем дело, как работает Release я в общем то знаю (код то доступен). Другой вопрос: ну и что? Ну допустим я пытаюсь второй раз открыть ту же форму. Ну и что? Пример из [5] показывает, что факт неудаленности предыдущей формы не должен оказыать никакого влияния - должно сгенериться новое уникальное имя.
MU (2005-03-01 12:42:00) [30]Destroys the form and frees its associated memory.
procedure Release;
Description
Use Release to destroy the form and free its associated memory.
Release does not destroy the form until all event handlers of the form and event handlers of components on the form have finished executing. Release also guarantees that all messages in the form's event queue are processed before the form is released. Any event handlers of the form should use Release instead of Free. Failing to do so could lead to an access violation.
Note: Release returns immediately to the caller. It does not wait for the form to be freed before returning.
Димон (2005-03-01 12:39:00) [31]Еще подлость в том, что подебужить classes нормально не получается: все строки съехавшие, т.е. часто ходишь по пустым местам, тогда как у нормальных строк не стоит слева точечка :(((
Димон (2005-03-01 12:30:00) [32]
> [9] Юрий Зотов © (01.03.05 12:27)
> Загадок стало еще больше
Да сам в загадках.
> Надо сымитировать ошибку при обработке и ходить отладчиком.
Не получается - она, зараза, неведенная. Т.е. некоторая последовательность играет роль.
> Ясно одно - при ошибке не уничтожается какой-то контейнер
Опять же повторю, что вроде бы в этом случае должно сгенериться новое уникальное имя. Мой пример из [5] показывает это.
Т.е. такое ощущение, что что-то уничтожилось но не до конца :))
Юрий Зотов (2005-03-01 12:27:00) [33]> Димон (01.03.05 12:20) [7]
Загадок стало еще больше. Надо сымитировать ошибку при обработке и ходить отладчиком.
Ясно одно - при ошибке не уничтожается какой-то контейнер (например, форма), а потом этот же контейнер загружается - отсюда и дубликат имен. Если ошибки нет, то контейнер уничтожается и при загрузке все проходит ОК.
Димон (2005-03-01 12:22:00) [34]
> [6] Юрий Зотов © (01.03.05 12:18)
Тода как объяснить работоспособность моего кода из [5]?
Димон (2005-03-01 12:20:00) [35]
> [4] Юрий Зотов © (01.03.05 12:13)
Добрый день, Юрий.
1) Код обработки показать не могу. Это тысяч 15 строк. Фактически это построение поискового sql запроса к базе sql на основе развернутых метаданных и текущего состояния ResultObject.
2) Если ближе к телу, то код такой
CLASS FUNCTION TForm_MLDocumentFilter._Execute(
const aFrameFilterClass: TFrame_MLChapterItemClass;
const aFilter: IMLFilter;
const aCls: TMLChapterItemClass): Boolean;
VAR
kForm: TForm_MLDocumentFilter;
kFilter: IMLFilter;
BEGIN
// Создаем копию фильтра
kFilter := aFilter.__Clone();
// Создаем форму
kForm := TForm_MLDocumentFilter.fCreate(aFrameFilterClass, kFilter, aCls);
try
// Выполняем форму в модальном режиме
Result := kForm.ShowModal = mrOk;
// Если пользователь нажал кнопку OK то копируем из временного объекта в постоянный
if Result then aFilter.__Assign(kFilter); // Это SaveResults из примера
finally
kForm.Release();
end;
END;
где fCreate это конструктор вызывающий inherited Create(application) + несколько простых действий.
3) Код saveResults - это просто копирование значений объекта.
Юрий Зотов (2005-03-01 12:18:00) [36]> Вроде бы TComponent должен сам заботиться о выборе имени
Выбор уникального имени - задача дизайнера, а не компонента. Откройте DFM - там имена уже жестко проставлены. Они же жестко прописаны в коде, как ссылочные published-поля и по ним как раз и идет инициализация этих полей при чтении DFM (см. FieldAddress).
Димон (2005-03-01 12:15:00) [37]
> в ран-тайме не должен
Раааазве. А ты попробуй :)))
showmessage(TForm2.create(application).name);
showmessage(TForm2.create(application).name);
showmessage(TForm2.create(application).name);
showmessage(TForm2.create(application).name);
Прекрасно отработает каждый раз генеря новое имя :)
Юрий Зотов (2005-03-01 12:13:00) [38]Нужно видеть:
- код SaveResults;
- ResultObject (хотя бы, как объявлен, где и как создается и уничтожается);
- код обработки.
Димон (2005-03-01 12:12:00) [39]
> В каком месте кода идёт возбуждение и что за обработка идёт?
Сразу после.
Но связь интересующей меня ошибки с ошибкой при обработке ResultObject это только мое предположение, т.к. ошибка происходит у заказчика. И заказчик не может описать что он делал до получения "a component named ... already exists".
Я предполагаю, что форма как-то некорректно удаляется или еще что. Собственно я бы мог разобраться с формированием имени в модуле classes. Но я бы очень хотел прежде чем это делать (все-таки там немало кода) услышать мнения общественности. Может кто с этим сталкивался.
clickmaker (2005-03-01 12:10:00) [40]
> Проде бы TComponent должен сам заботиться о выборе имени
>
в ран-тайме не должен