У меня есть приложение Delphi 6, которое сильно многопоточно. У меня есть компонент, который я создал, который происходит от TWinControl. Когда я его впервые построил, я использовал скрытое окно, и WndProc обрабатывал сообщения, выделенные AllocateHwnd(). Недавно я начал очищать WndProc в своем коде и решил удалить вспомогательный WndProc(). Я изменил компонент, чтобы вместо этого переопределить метод базового класса WndProc() и выполнить обработку пользовательских сообщений Windows. В этом WndProc() я сначала вызвал унаследованный обработчик, а затем обработал свои пользовательские сообщения (смещения WM_USER), установив для поля «Сообщение» значение «1», если нашел одно из моих пользовательских сообщений и обработал его.Как мог WndProc() Delphi 6 TWinControl выполнять потоки основного потока VCL?
Одно важное примечание. Я положил строку кода в верхней части переопределения WndProc(), которая генерирует исключение, если текущий идентификатор потока не является основным потоком VCL. Я хотел убедиться, что WndProc() выполняется только в контексте основного потока VCL.
После этого и запуска моей программы я столкнулся с чем-то, что кажется действительно причудливым. Я запускал свою программу как обычно и выполнял различные задачи без ошибок. Затем, когда я пошел в элемент управления TMemo, который находится на той же странице, что и мой потомок TWinControl. Если я щелкнул внутри, что TMemo контролирует проверку основного потока в моем переопределении WndProc(). У меня была точка останова на нем, и когда я пошел в стек вызовов, там ничего не было выше моего переопределения WndProc().
Насколько я могу судить, и я дважды проверял, я не делаю явных вызовов переопределения WndProc(). Это не то, что я когда-либо делал. Но учитывая, что мой компонент TWinControl был бы создан в основном потоке VCL, как и все остальные компоненты, я не могу понять, как переопределение WndProc() будет выполняться в контексте фонового потока, особенно когда действие UI, например произойдет щелчок мышью. Я понимаю, как мой WndProc() привязан к элементу управления TMemo, поскольку все дочерние окна висят от окна верхнего уровня WndProc(), по крайней мере, это мое понимание. Но так как все окна компонентов были бы созданы в основном потоке VCL, тогда все очереди сообщений тоже должны исполняться в этом контексте, верно?
Итак, какую ситуацию я мог бы создать, чтобы выполнить мой WndProc(), и только иногда, в контексте фонового потока?
Спасибо. Я видел проблему с обработанным дескриптором, где из-за недействительной ссылки на окно, которую я перенесла один раз. Это одна из причин, по которой я инстинктивно занимаюсь AllocateHWND(), когда я не должен (я помню ваши комментарии к этому из другого потока). Есть ли способ в коде, чтобы я мог поймать рабочий поток, который захватывает дескриптор в простой вид? У меня много активности потоков, и я бы хотел быстро решить эту проблему, если бы не смог, без полной проверки кода. Что-то, что может вызвать исключение, когда поток попытался получить доступ к дескриптору, возможно? –
попробуйте переопределить метод 'CreateWnd()' или 'CreateWindowHandle()' компонента и создать собственное исключение, если контекст вызывающего потока неверен. Но на самом деле, НИКОГДА не обращайтесь к свойству 'TWinControl.Handle' из рабочего потока для начала, если только он не обернут вызовом' TThread.Synchronize() '. –
Спасибо. Это то, что мне нужно. –