Недопустимый дескриптор окна 1400 как исправить

Обновлено: 27.04.2024

Поскольку я новичок в потоковой передаче, я столкнулся с проблемой:

Я отследил это до доступа к списку, это выглядит так:

Если я пропущу эту часть списка, ошибка никогда не произойдет, поэтому я думаю, что что-то может быть не так в моем коде потока, который портит vcl / gui, вероятно, потому, что он все еще работает, пока осуществляется доступ к VCL? Если я проверю список, то после завершения потока с ним будет что-то очень странное, иногда список даже не отображается или добавленные элементы не доступны для нажатия.

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

if Assigned(sObj.xOnAsyncRequestDone) then sObj.xOnAsyncRequestDone;

Как я мог это решить?

Обычно такая ошибка возникает, если вы создаете дескриптор окна в одном потоке и уничтожаете его в другом потоке.

Найдено, что Synchronize (), похоже, решает эту проблему (Synchronize (sObj.xOnAsyncRequestDone);). Какие-либо другие соображения или изменения, которые могут помочь избежать таких проблем?

Каждый раз, когда вашим потокам необходимо вызвать основной поток (VCL не является потокобезопасным), им необходимо использовать Synchronize. Одна из вещей, которые я делаю, - это пытаюсь сделать вызовы Synchronize короткими и приятными. Обычно они вызывают метод в основном потоке, который затем использует PostMessage. Это позволяет потоку вернуться к тому, что он делал, без замедления из-за синхронизации. Это также позволяет основному потоку знать об изменениях и делать то, что ему нужно.

Вы разместили много кода, но не ключевую, релевантную часть. В частности, реализация вашего xOnAsyncRequestDone обработчика / метода событий (если только он буквально не вызывает только тот метод журнала, который вы опубликовали).

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

ПРИМЕЧАНИЕ. Это основа Windows, а не Delphi .

Здесь стоит отметить, что дескрипторы окон в VCL часто могут создаваться косвенно. Вы не обязательно увидите явное создание элемента управления, который отмечает создание базового дескриптора окна. Довольно часто оконные ручки создаются только при необходимости. Аналогичным образом изменение свойств элемента управления может привести к тому, что VCL попытается воссоздать окно для этого элемента управления, уничтожив текущее окно в процессе.

Должно быть совершенно очевидно, что эти механизмы очень уязвимы для проблем, которые могут возникнуть, когда методы VCL вызываются потоками, отличными от потока VCL. Вот почему вы часто здесь говорите, что « VCL не является потокобезопасным ».

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

Синхронизация для спасения

Фактически, именно поэтому Synchronize существует.

Механизм, который вы вызываете, на Synchronize самом деле работает, чтобы гарантировать, что метод, который вы синхронизируете, выполняется в потоке VCL. Если это на самом деле создание дескриптора окна, то, когда поток VCL позже придет, чтобы уничтожить этот дескриптор окна, он вполне может это сделать, поскольку он фактически его создал.

Значит, ваша проблема решена.

Другие варианты

Однако этот Synchronize механизм довольно сложен, он решает (в наши дни), помимо прочего, кроссплатформенные проблемы, и в результате в этом случае может оказаться излишним.

Вы можете думать об этом как о системе «Синхронизация», «встроенной» в ОС.

НЕ рекомендация

Это не означает, что я рекомендовал бы эту альтернативу в данном случае. Хотя кажется, что это может быть уместно, учитывая, что в данном случае это действительно простое уведомление «работа завершена», без более полного понимания ваших конкретных потребностей невозможно сказать, что является наиболее подходящим.

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

Это наиболее распространенное условие «IE Error Code 1400», известное как ошибка времени выполнения (ошибка). Разработчики тратят много времени и усилий на написание кода, чтобы убедиться, что Internet Explorer стабилен до продажи продукта. Как и во всем в жизни, иногда такие проблемы, как ошибка 1400, упускаются из виду.

Почему происходит ошибка времени выполнения 1400?

Сбой устройства или Internet Explorer обычно может проявляться с «IE Error Code 1400» в качестве проблемы во время выполнения. Три распространенные причины, по которым ошибки во время выполнения, такие как всплывающее окно ошибки 1400:

Ошибка 1400 Crash - Ошибка 1400 является хорошо известной, которая происходит, когда неправильная строка кода компилируется в исходный код программы. Обычно это происходит, когда Internet Explorer не может обработать данные в удовлетворительной форме и поэтому не может получить ожидаемый результат.

Утечка памяти «IE Error Code 1400» - Когда Internet Explorer обнаруживает утечку памяти, операционная система постепенно работает медленно, поскольку она истощает системные ресурсы. Потенциальным фактором ошибки является код Microsoft Corporation, так как ошибка предотвращает завершение программы.

Ошибка 1400 Logic Error - Логическая ошибка вызывает неправильный вывод, даже если пользователь дал действительные входные данные. Виновником в этом случае обычно является недостаток в исходном коде Microsoft Corporation, который неправильно обрабатывает ввод.

Распространенные проблемы IE Error Code 1400

Общие проблемы IE Error Code 1400, возникающие с Internet Explorer:

  • «Ошибка в приложении: IE Error Code 1400»
  • «IE Error Code 1400 не является программой Win32. «
  • "Возникла ошибка в приложении IE Error Code 1400. Приложение будет закрыто. Приносим извинения за неудобства."
  • «Не удается найти IE Error Code 1400»
  • «IE Error Code 1400 не может быть найден. «
  • «Ошибка запуска в приложении: IE Error Code 1400. «
  • «Не удается запустить IE Error Code 1400. «
  • "Отказ IE Error Code 1400."
  • «Ошибка пути программного обеспечения: IE Error Code 1400. «

Истоки проблем IE Error Code 1400

Проблемы IE Error Code 1400 могут быть отнесены к поврежденным или отсутствующим файлам, содержащим ошибки записям реестра, связанным с IE Error Code 1400, или к вирусам / вредоносному ПО.

m_hook_window:= TWinControl.Create(nil);
m_hook_window.Visible:=false;
m_hook_window.Left:=-1;
m_hook_window.Top:=-1;
m_hook_window.Width:=1;
m_hook_window.Height:=1;
m_hook_window.ParentWindow:=Application.Handle;

Ну и меняю его обработчик на свой.

Все отлично работает.

Останавливаю поток из программы и вызываю Destroy, а на строке
m_hook_window.Free;

Выдает ошибку EOSerror: "System Error. Code 1400: Недопустимый дескриптор окна". Как побороть?

> Ну и меняю его обработчик на свой.
> Все отлично работает.

> Останавливаю поток из программы и вызываю Destroy, а на
> строке
> m_hook_window.Free;

Оное деяние весьма сомнительно.

А приложение win32?

--
Regards, LVT.

← →
Набережных С. © ( 2005-02-27 20:02 ) [2]

По-моему AllocateHWND не являтся потокобезопасной.

← →
Vand777 © ( 2005-02-27 20:27 ) [3]

2 Leonid Troyanovsky: спасибо. Так заработало без исключений.

Ну чтобы что-то присвоить m_hook_window.ParentWindow. А что еще можно присвоить?

> m_hook_window.Free;
>Оное деяние весьма сомнительно.

P.S. Приложение Win32.

← →
Vand777 © ( 2005-02-27 21:30 ) [5]

А почему мой первоначальный вариант был плох? Ведь к этому m_hook_window обращался только один поток?

Почему тут страдает "потокобезопсаность"? Из-за наличия Application.processmessages в потоке?

← →
Leonid Troyanovsky © ( 2005-02-27 22:25 ) [6]


> Vand777 © (27.02.05 20:27) [3]

> Ну чтобы что-то присвоить m_hook_window.ParentWindow. А
> что еще можно присвоить?

Хендл окна, созданного в том же потоке.
Хотя, видимо, не очень удачен сам замысел использования дочернего окна.

> > m_hook_window.Free;
> >Оное деяние весьма сомнительно.

Если с самого начала, то и само создание окна сомнительно,
бо если оно создается в конструкторе, то это не окно
создаваемого потока.
Ну, и с разрушением не все гладко, бо контролы включаются
в массив Controls and so on. Плюс последовательность -
при завершении потока окна уже нет (окно - собственность потока).

> 2 Набережных С.: так можно мне использовать AllocateHWND?
> Может какие-то доп. меры принять для увеличения

Использовать следует с оглядкой, т.к. AllocateHwnd не является потокобезопасным (Набережных С. © (27.02.05 20:42) [4]).
Однако, если оные потоки (окна) не создаются многопоточно и ежемилисекундно, то и проблем нет.
Ну, а в сомнительных случаях можно собс-ручно защитить вызов посредством критической секции.

m_hook_window:= TWinControl.Create(nil);
m_hook_window.Visible:=false;
m_hook_window.Left:=-1;
m_hook_window.Top:=-1;
m_hook_window.Width:=1;
m_hook_window.Height:=1;
m_hook_window.ParentWindow:=Application.Handle;

Ну и меняю его обработчик на свой.

Все отлично работает.

Останавливаю поток из программы и вызываю Destroy, а на строке
m_hook_window.Free;

Выдает ошибку EOSerror: "System Error. Code 1400: Недопустимый дескриптор окна". Как побороть?

> Ну и меняю его обработчик на свой.
> Все отлично работает.

> Останавливаю поток из программы и вызываю Destroy, а на
> строке
> m_hook_window.Free;

Оное деяние весьма сомнительно.

А приложение win32?

--
Regards, LVT.

← →
Набережных С. © ( 2005-02-27 20:02 ) [2]

По-моему AllocateHWND не являтся потокобезопасной.

← →
Vand777 © ( 2005-02-27 20:27 ) [3]

2 Leonid Troyanovsky: спасибо. Так заработало без исключений.

Ну чтобы что-то присвоить m_hook_window.ParentWindow. А что еще можно присвоить?

> m_hook_window.Free;
>Оное деяние весьма сомнительно.

P.S. Приложение Win32.

← →
Vand777 © ( 2005-02-27 21:30 ) [5]

А почему мой первоначальный вариант был плох? Ведь к этому m_hook_window обращался только один поток?

Почему тут страдает "потокобезопсаность"? Из-за наличия Application.processmessages в потоке?

← →
Leonid Troyanovsky © ( 2005-02-27 22:25 ) [6]


> Vand777 © (27.02.05 20:27) [3]

> Ну чтобы что-то присвоить m_hook_window.ParentWindow. А
> что еще можно присвоить?

Хендл окна, созданного в том же потоке.
Хотя, видимо, не очень удачен сам замысел использования дочернего окна.

> > m_hook_window.Free;
> >Оное деяние весьма сомнительно.

Если с самого начала, то и само создание окна сомнительно,
бо если оно создается в конструкторе, то это не окно
создаваемого потока.
Ну, и с разрушением не все гладко, бо контролы включаются
в массив Controls and so on. Плюс последовательность -
при завершении потока окна уже нет (окно - собственность потока).

> 2 Набережных С.: так можно мне использовать AllocateHWND?
> Может какие-то доп. меры принять для увеличения

Использовать следует с оглядкой, т.к. AllocateHwnd не является потокобезопасным (Набережных С. © (27.02.05 20:42) [4]).
Однако, если оные потоки (окна) не создаются многопоточно и ежемилисекундно, то и проблем нет.
Ну, а в сомнительных случаях можно собс-ручно защитить вызов посредством критической секции.

← →
Aleksandr ( 2003-12-04 12:20 ) [0]

Стал трассировать - ошибка вылетает на

procedure TWinControl.DestroyWindowHandle;
begin
Include(FControlState, csDestroyingHandle);
try
if not Windows.DestroyWindow(FHandle) then
RaiseLastOSError;
finally
Exclude(FControlState, csDestroyingHandle);
end;
FHandle := 0;
end;

Еще конкретнее - когда происходит уничтожение главного окна и в его дестракторе доходит очередь до одной из панелей, на которой располагаются ProgressBar, SpeedButton и ListBox, то вызов ее DestroyWindowHandle и приводит к ошибке. Что может быть причиной ошибки? Панель в основном невидима. Кстати, та же ошибка иногда появляется при попытке сделать ее видимой.

← →
Семен Сорокин ( 2003-12-04 12:27 ) [1]

ошибка, скорее всего, в 17 строке

← →
Aleksandr ( 2003-12-04 12:47 ) [2]

Гм. в 17-й от чего и в чем?

← →
Семен Сорокин ( 2003-12-04 12:53 ) [3]

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

← →
Aleksandr ( 2003-12-04 13:41 ) [4]

Ну так я и прошу опытных помочь с подсказкой, какие действия могут привести к таким проблемам с визуальными компонентами.

← →
Shirson ( 2003-12-04 19:36 ) [5]

Не, тут не 17я строка. Тут гремлины. Без шуток.

У меня эта байда вываливалась, когда я ДБРичЕдит ложил на форму, разворачивал в клиента и ставил висибл в фалш. (дизайн-моде)
Закрываешь форму - лови 1400.

Ставишь визибл в тру - всё работает.

При создании формы делаешь визибл - фальш, лови 1400.

В процессе работы, когда форма уже открылась, визибл - фальш. - работает.

Гремлины, не иначе. Что за чертовщина до конца не разобрался, спрятал его под другую компоненту (визибл - тру) и плюнул. С Обычным ричедитом, который лежит там-же такого не наблюдается.

Читайте также: