powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / отправить сообщение "главному потоку" из "дочернего"
77 сообщений из 77, показаны все 4 страниц
отправить сообщение "главному потоку" из "дочернего"
    #39623530
неглавный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
пишется простенький DCOM-сервис с использованием midas'а.
в нем фабрикой создаются экземпляры класса TDCOMmodule = class(TRemoteDataModule, IMyServ)
при этом, у этого сервиса есть ещё и GUI-окно, оно же MainForm.
мне нужно из экземпляра класса TDCOMmodule отправить сообщение этому окошку.

если использовать из потока в котором живёт TDCOMmodule вызов
Код: pascal
1.
PostMessage(MainForm.Handle, WM_USER + XXX, WParam, LParam)

это будет безопасно?
нет ли подводных камней?
или есть что-то более правильное для передачи информации "главному потоку"?
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39623536
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
неглавныйэто будет безопасно?

Это будет настолько безопасно насколько программист понимает что делает.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39623540
неглавный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Sibiryakovнеглавныйэто будет безопасно?Это будет настолько безопасно насколько программист понимает что делает.ну, я не настоящий сварщик, я только учусь.
если тут есть где споткнуться, подскажите пожалуйста.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39623543
Фотография DarkMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
неглавный,

Посмотри код wadman`a в соседней, недавно поднятой ветке.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39623557
неглавный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DarkMasterПосмотри код wadman`a в соседней, недавно поднятой ветке.это там где 17 страниц ветка?
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39623564
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
неглавный,

а в качестве WParam, LParam что отправляешь?
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39623597
Олег Третьяков
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
неглавный,
В межпоточном обмене основных подводных камней - два: синхронизация и время валидности параметров, переданных по сслылке.
PostMessage - потокобезопасен. Ты положил сообщение в очередь и пошел дальше.
Если ты будешь передавать некие значения, которые влезут по размеру wParam и lParam, то это безопасно.
Если же тебе надо передать что-то большее(доблы, строку, структуру, объект), то нужно озаботиться валидностью экземпляра и его потобезопасностью на момент выборки сообщений. Как - зависит от твоих хотелок и задумок.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39623617
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Олег ТретьяковPostMessage - потокобезопасен.
имхо, как раз PostMessage, потокоНЕбезопасен, если ты передаешь указатель, валидность которого будет потеряна к моменту, когда он будет извлечен из очереди сообщений для обработки основным потоком.
А вот SendMessage, наоборот, не даст потоку продолжиться дальше (и завершиться), пока сообщение не будет обработано.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39623621
Олег Третьяков
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ДокОлег ТретьяковPostMessage - потокобезопасен.
имхо, как раз PostMessage, потокоНЕбезопасен, если
Это персональные тонкости мировосприятия или уже устал и не вник?
Олег Третьяковто нужно озаботиться валидностью экземпляра и его потобезопасностью на момент выборки сообщений. - для способа с PostMessage
Он может уже и не нужен в контексте потока - обработался, выплюнулся.
Допустима и\или нужна блокировка потока-исполнителя? Ну дык и SendMessage в руки. Ты телепат? Я - нет.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39623622
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ДокОлег ТретьяковPostMessage - потокобезопасен.
имхо, как раз PostMessage, потокоНЕбезопасен, если ты передаешь указатель, валидность которого будет потеряна к моменту, когда он будет извлечен из очереди сообщений для обработки основным потоком.
А вот SendMessage, наоборот, не даст потоку продолжиться дальше (и завершиться), пока сообщение не будет обработано.

Во-первых, никто не мешает испортить валидность после SendMessage. Дурковать так дурковать.
Во-вторых - нафига такие multi-threaded приложения, если вызывающая нить будет ждать завершения задания в вызываемой.
В третьих, да, случаи могут быть разными, к чему такая категоричность.
В четвертых, SendMessage из другой нити не просто блокируется в ожидании ответа, а в процессе ожидания продолжает обрабатывать некоторые входящие сообщения и получить удивительное поведение в отдельных случаях. Если ты, конечно, не вызывал SendMessageTimeout с SMTO_BLOCK, о чем ты не упомянул.

В пятых, PostMessage как апишная функция MS Windows- потокобезопасен.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39623714
неглавный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо всем за пояснения. Картина проясняется.
Передавать планмруется небольшие структуры по ссылке.
Поясните пожалуйста, почему ссылка может стать невалидной?
Как этого избежать?
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39623716
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
неглавныйСпасибо всем за пояснения. Картина проясняется.
Передавать планмруется небольшие структуры по ссылке.
Поясните пожалуйста, почему ссылка может стать невалидной?
Как этого избежать?
Глупости, не обращай внимания.
...
Тред-передатчик: в куче выделяет память под структуру. Копирует в выделенную память нужные данные.
Передает ссылку в другую нить (например так, как ты собирался). После обработки данных, тред-приемник освобождает память, ссылку на которую ему передал передали.
Возможные глюки: очередь сообщений не бесконечная, если приемник не будет успевать обработать - сообщения потеряются.
Если структура крошечная, не более размера параметров сообщения - передавай данные прямо в параметрах, без ссылки.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39623722
неглавный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо. :)
Структурые небольшие, но в параметры не влезут.
Какой менеджер памяти нужно использовать:
достаточно стандартного Дельфийского, или нужно Виндовый?
Интенсивность передачи оных сообщений невелика.
Переполнение очереди маловероятно.
Да и ценность сообщений тоже не критична - по большей части информационная.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39623725
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
неглавный,
любой менеджер, лишь бы выделение памяти и освобождение в одном и том же делалось.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39623727
неглавный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
чччД, спасибо!
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39623807
V.Borzov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: pascal
1.
2.
3.
4.
    synchronize(
      procedure begin
        // любой код, выполняемый в главном потоке приложения
      end);


Тоже безопасно... Иногда не без удовольствием пользуюсь им :)
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39623816
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TThreadedQueue<T>
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39624593
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
чччДВ пятых, PostMessage как апишная функция MS Windows- потокобезопасен.
Каким макаром?
чччДнеглавный,
любой менеджер, лишь бы выделение памяти и освобождение в одном и том же делалось.
Ерунда. Выделил в одном потоке, переслал второму, тот получил и удалил
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39624645
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2Ерунда. Выделил в одном потоке, переслал второму, тот получил и удалил
В одном и том же менеджере, ваш Кэп.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39624714
V.Borzov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2Ерунда. Выделил в одном потоке, переслал второму, тот получил и удалилА есть гарантия, что адресат это сообщение в результате получит, обработает и удалит то, что требуется удалить? Когда SendMessage, там понятно, а PostMessage не дожидается ответа, пуляет и уходит.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39624851
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvpВ одном и том же менеджере, ваш Кэп.
Тогда да. Спасибо, Кэп!
V.BorzovА есть гарантия, что адресат это сообщение в результате получит, обработает и удалит то, что требуется удалить? Когда SendMessage, там понятно, а PostMessage не дожидается ответа, пуляет и уходит.
Не получить он может только в одном случае - если оно не отправится. А для этого достаточно вспомнить, что PostMessage это функция
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39624883
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2alekcvpВ одном и том же менеджере, ваш Кэп.
Тогда да. Спасибо, Кэп!
V.BorzovА есть гарантия, что адресат это сообщение в результате получит, обработает и удалит то, что требуется удалить? Когда SendMessage, там понятно, а PostMessage не дожидается ответа, пуляет и уходит.
Не получить он может только в одном случае - если оно не отправится. А для этого достаточно вспомнить, что PostMessage это функция
Ты не видишь разницы между фактом получения сообщения из очереди и фактом его обработки.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39624885
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2Не получить он может только в одном случае - если оно не отправится.
Ложь и провокация. В любой момент цикл обработки очереди может завершиться по обычно непредсказуемым для вызывателя PostMessage причинам, не обработав при этом такие и все остальные другие сообщения.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39624890
V.Borzov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2,
И что возвращает функция PostMessage?
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39624893
Фотография DarkMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
V.BorzovВасилий 2Ерунда. Выделил в одном потоке, переслал второму, тот получил и удалилА есть гарантия, что адресат это сообщение в результате получит, обработает и удалит то, что требуется удалить? Когда SendMessage, там понятно, а PostMessage не дожидается ответа, пуляет и уходит.

Более того, при переполнении очереди сообщений - PostMessage() просто обламывается и ничего не шлет. Т.е. возможна ситуация, когда адресат просто ничего не получит.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39624894
Фотография DarkMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
V.BorzovВасилий 2,
И что возвращает функция PostMessage?

BOOL
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39624911
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DarkMasterБолее того, при переполнении очереди сообщений - PostMessage() просто обламывается и ничего не шлет. Т.е. возможна ситуация, когда адресат просто ничего не получит.
Да, но в этом случае PostMessage, скорее всего, FALSE вернет.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39624912
Фотография DarkMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockDarkMasterБолее того, при переполнении очереди сообщений - PostMessage() просто обламывается и ничего не шлет. Т.е. возможна ситуация, когда адресат просто ничего не получит.
Да, но в этом случае PostMessage, скорее всего, FALSE вернет.

Конечно.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39624922
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DarkMasterYuRockпропущено...

Да, но в этом случае PostMessage, скорее всего, FALSE вернет.

Конечно.
Ну вот, и значит, проверив результат PostMessage, можно будет сразу освободить выделенную память, указатель на которую передавался в параметры сообщения.
А вот если она TRUE вернёт - то никакой гарантии освобождения памяти (или еще чего) нет, т.к. нет гарантии обработки.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39624927
V.Borzov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2,

Насчет PostMessage: она не дожидается, когда адресат получит сообщение, поэтому очищать данные, например буфер передаваемой строки - ошибка. в SendMessage именно так и работаем: передаем в качестве параметра указатель на строку или структуру, а после выполнения функции - удаляем, если требуется. PostMessage либо доставит в итоге ссылку на удаленные данные, либо, если обеспечить их сохранность, понадеясь на то, что их удалит адресат, то нет гарантии, что тот их вообще получит, и данные не повиснут в памяти мертвым грузом. Поскольку PostMessage, само собой, отработает быстрее всего, не заставляя поток ждать ответа от другого потока, то у меня была идея собрать стэк данных, данные создаются там, и ссылка на них передается между потоками. Но тут выходит, что для обработки стека требуются его блокировки, опять же, и получается, что меняю шило на мыло, и я просто
воспользовался sendmessage. Правда задача у меня гораздо проще: обмен данных исполняющего запрос потока с главным потоком приложения, чтобы то отрисовало статус запроса. К тому же, после того, как захотелось еще, чтобы юзер мог и остановить процесс, то выяснилось, что никуда не деться от SendMessage в принципе: и теперь я отправляю основному потоку приложения сообщение, он обрабатывает его, рисуя юзеру статус, при этом получает от юзера, возможно, нажатие кнопки "не хочу ждать, пусть всё прекратится, остановите это!!", и возвращаю результат передавшему потоку. В итоге, конечно, если основной поток зависнет, или в основном потоке запустят другой запрос, то все мои потоки встанут, конечно.

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

Прошу поправить, если я где-то в своих утверждениях ошибся.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39624932
V.Borzov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DarkMasterV.Borzovпропущено...
А есть гарантия, что адресат это сообщение в результате получит, обработает и удалит то, что требуется удалить? Когда SendMessage, там понятно, а PostMessage не дожидается ответа, пуляет и уходит.

Более того, при переполнении очереди сообщений - PostMessage() просто обламывается и ничего не шлет. Т.е. возможна ситуация, когда адресат просто ничего не получит.
О! А вот это уже интересно! Спасибо за информацию.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39624968
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DarkMasterV.Borzovпропущено...
А есть гарантия, что адресат это сообщение в результате получит, обработает и удалит то, что требуется удалить? Когда SendMessage, там понятно, а PostMessage не дожидается ответа, пуляет и уходит.

Более того, при переполнении очереди сообщений - PostMessage() просто обламывается и ничего не шлет. Т.е. возможна ситуация, когда адресат просто ничего не получит.
Удалось-ли хоть раз столкнуться с такой ситуацией?
У меня в промышленных масштабах на откровенно дохлых машинах ни разу не вышло. :(
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39624974
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
V.Borzovхотя OnTerminate делает то же самое, собственно, причем исполняется он в главном потоке
Ну понятно :)
Код: pascal
1.
2.
3.
4.
procedure TThread.DoTerminate;
begin
  if Assigned(FOnTerminate) then Synchronize(CallOnTerminate);
end;
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39624977
Фотография DarkMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadmanDarkMasterпропущено...


Более того, при переполнении очереди сообщений - PostMessage() просто обламывается и ничего не шлет. Т.е. возможна ситуация, когда адресат просто ничего не получит.
Удалось-ли хоть раз столкнуться с такой ситуацией?
У меня в промышленных масштабах на откровенно дохлых машинах ни разу не вышло. :(

Насколько знаю - на исскуственных тестах кто-то воспроизводил. Длина очереди 10000 сообщений, так что при желании можно что-то такое вытворить. А то, что у тебя не вышло - так радоваться нужно
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39624978
V.Borzov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock...
Ну понятно :)
Код: pascal
1.
2.
3.
4.
procedure TThread.DoTerminate;
begin
  if Assigned(FOnTerminate) then Synchronize(CallOnTerminate);
end;


Ой, точно! :)
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39624983
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadmanУдалось-ли хоть раз столкнуться с такой ситуацией?
Такое легко получить, если:
1. обработчик любого сообщения зависнет, а PostMessage продолжают регулярно посылаться;
2. сообщения шлются чаще, чем обрабатываются (например, шлются каждую секунду, а обработка занимает 2 секунды).

Особенности [ошибки] логики программы. Это от дохлости машин мало зависит.

Ты не получал такого по двум причинам:
1. Таких ошибок не допускал;
2. На самом деле получал, но не замечал, и не ты, а твои клиенты
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39624987
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DarkMasterНасколько знаю - на исскуственных тестах кто-то воспроизводил.
Ну вот... Так любой может.
YuRock2. На самом деле получал, но не замечал, и не ты, а твои клиенты
Мои клиенты это производство. Пропущенное сообщение это строчка в базе с логистикой. Нет строчки, нет отгрузки.
YuRockТакое легко получить, если:
Не получалось почему-то. Но тут упорно об этом пишется теоретиками. Шах и мат.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39624994
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А я видел как в винде систему сообщений раком ставит.

После чего адски тормозит ВСЕ при загрузке проца в 1%.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625001
Фотография DarkMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadmanНе получалось почему-то. Но тут упорно об этом пишется теоретиками. Шах и мат.

Ну вот так вот Зачем-то же PostMessage() функцией сделали - значит предполагали, что возможна ситуация обломинго для нее.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625011
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
V.Borzov...в SendMessage именно так и работаем: передаем в качестве параметра указатель на строку или структуру, а после выполнения функции - удаляем, если требуется...

Мы все еще про мультитрейдинг?
А какой смысл в таком мултитрейдинге, если нужно ждать результата обработки? Или у тебя принимающий диспетчер сообщений сразу же как-то передаст полученное сообщение какому-то следующему обработчику и сразу же выйдет на очередную итерацию обработки очереди? Что за чушь вообще обсуждается?
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625023
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadmanМои клиенты это производство. Пропущенное сообщение это строчка в базе с логистикой. Нет строчки, нет отгрузки.
Фигня. У меня поток работы с купюроприёмником PostMessage шлёт при принятии купюры
Правда, недостач тоже не бывало пока.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625024
V.Borzov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
чччДV.Borzov...в SendMessage именно так и работаем: передаем в качестве параметра указатель на строку или структуру, а после выполнения функции - удаляем, если требуется...

Мы все еще про мультитрейдинг?
А какой смысл в таком мултитрейдинге, если нужно ждать результата обработки? Или у тебя принимающий диспетчер сообщений сразу же как-то передаст полученное сообщение какому-то следующему обработчику и сразу же выйдет на очередную итерацию обработки очереди? Что за чушь вообще обсуждается?
Моя задача такая: открываем форму, нажимаем "выполнить запрос". Требуется, чтобы, во-первых, приложение не замерзло на время выполнения запроса, чтобы была возможность заниматься еще чем-то, вызвать, например, еще пару запросов в отдельных потоках, а во-вторых, чтобы юзер или самое приложение могли остановить запрос.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625028
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockwadmanМои клиенты это производство. Пропущенное сообщение это строчка в базе с логистикой. Нет строчки, нет отгрузки.
Фигня. У меня поток работы с купюроприёмником PostMessage шлёт при принятии купюры
Правда, недостач тоже не бывало пока.
Купюры идут одним потоком и с определенной скоростью. Тут даже кпк справится.

Но если кому мало 10 тыс, то в HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows в ключике USERPostMessageLimit можно увеличить очередь. По умолчанию там эти самые 10000.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625080
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
чччДТы не видишь разницы между фактом получения сообщения из очереди и фактом его обработки.
Нет, ты ошибаешься
YuRockВасилий 2Не получить он может только в одном случае - если оно не отправится.
Ложь и провокация. В любой момент цикл обработки очереди может завершиться по обычно непредсказуемым для вызывателя PostMessage причинам, не обработав при этом такие и все остальные другие сообщения.
Пруфы или же сам лжешь.
Где в цикле
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
try
  while not Terminated do
    GetMessage
    ...process...
except
  ...
end;
while GetMessage do
  ... just free memory ...


Могут всплыть эти непредсказуемые причины?
Варианты насильственного убиения потока не рассматриваются, это ситуации нештатные, и с ними в любом случае ничего не сделаешь.
YuRockА вот если она TRUE вернёт - то никакой гарантии освобождения памяти (или еще чего) нет, т.к. нет гарантии обработки.
В асинхронной модели нет никакой гарантии вообще всего. За гарантиями велком в синхронное
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625083
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
V.BorzovТребуется, чтобы, во-первых, приложение не замерзло на время выполнения запроса, чтобы была возможность заниматься еще чем-то, вызвать, например, еще пару запросов в отдельных потоках, а во-вторых, чтобы юзер или самое приложение могли остановить запрос.
Ну а в нулевых, надо, чтобы СУБД поддерживал такую возможность. Таких СУБД не так много. А те, что поддерживают - поддерживают не всегда и/или с нюансами...

Короче, в общем случае такую задачу не решить просто потоками.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625093
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2Где в цикле ... Могут всплыть эти непредсказуемые причины?
Вот где (например):
Код: pascal
1.
2.
3.
4.
5.
6.
while GetMessage do begin
  ... just free memory ...

  if ПораЗакончитьЭтотЦиклПотомуЧтоЯТакХочу = True then
    Break;
end;



Или вот где:
Код: pascal
1.
2.
3.
4.
while GetMessage do begin
  ... just free memory ...
end;
// А вот тут мы уже вне цикла, т.к. пришел WM_QUIT, хотя после этого WM_QUIT была еще гора необработанных сообщений
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625098
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
V.BorzovНасчет PostMessage: она не дожидается, когда адресат получит сообщение, поэтому очищать данные, например буфер передаваемой строки - ошибка.
Разумеется. Поэтому данные, отправляемые Post-ом, должны быть либо постоянными, либо уникальными - т.е. созданными исключительно для отправки. Второй вариант для случая, например, строк - это копия, выделенная в куче через NewStr.

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

авторК тому же, после того, как захотелось еще, чтобы юзер мог и остановить процесс, то выяснилось, что никуда не деться от SendMessage в принципе: и теперь я отправляю основному потоку приложения сообщение, он обрабатывает его, рисуя юзеру статус, при этом получает от юзера, возможно, нажатие кнопки "не хочу ждать, пусть всё прекратится, остановите это!!", и возвращаю результат передавшему потоку.
Неправильно выяснилось. Отправляй своему вторичному потоку тем же Post-ом, или взводи ему флаг по типу Terminated и всё. Конечно, в коде потока интервал между проверками флага (или длина очереди) д.б. небольшими, иначе отмена сработает с большой задержкой. Нет, вариант с SendMessage тоже сработает, и для простых случаев с двумя потоками он вполне приемлем
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625101
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Для полного удовлетворения достаточно создать простой поток - посредник между доп.потоками и основным потоком.
Он выделяет память под передаваемые данные, он её освобождает по запросу или таймауту, либо допинывает при необходимости недошедшие данные до убитых, но восстановленных позднее потоков.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625107
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2и если грамотно написать обработку нештатных ситуаций
Да, только очень грамотный программист обернёт на всякий случай вызов winapi-шных функций в try...except, а потом еще, после окончания цикла обработки сообщений (и фактического разрушения очереди сообщений), будет надеяться, что повторный
Код: pascal
1.
while GetMessage do

поможет именно "дообработать" оставшиеся сообщения.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625108
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockВот где (например):
Код: pascal
1.
2.
3.
4.
5.
6.
while GetMessage do begin
  ... just free memory ...

  if ПораЗакончитьЭтотЦиклПотомуЧтоЯТакХочу = True then
    Break;
end;



Ерунда какая-то. Зачем в цикле очистки очереди досрочное прерывание?
авторИли вот где:
Код: pascal
1.
2.
3.
4.
while GetMessage do begin
  ... just free memory ...
end;
// А вот тут мы уже вне цикла, т.к. пришел WM_QUIT, хотя после этого WM_QUIT была еще гора необработанных сообщений


Здесь не исключено (если, конечно, не-gui потоку вообще возможно получение этого сообщения - но это если уже сам программер такое сделает, т.к. без явного прописывания это сообщение само собой от системы не приходит).
У меня на этот случай сделано так
Код: pascal
1.
2.
3.
4.
5.
6.
    // вычерпываем все сообщения из очереди и удаляем все выделенные куски
    while GetQueueStatus(QS_ALLEVENTS) <> 0 do
    begin
      GetMessage(MsgRec, 0, 0, 0);
      ProcessMsg(MsgRec, True);
    end;
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625111
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockДа, только очень грамотный программист обернёт на всякий случай вызов winapi-шных функций в try...except, а потом еще, после окончания цикла обработки сообщений (и фактического разрушения очереди сообщений), будет надеяться, что повторный
Код: pascal
1.
while GetMessage do

поможет именно "дообработать" оставшиеся сообщения.
Ну всё, пошла чушня.
1) При чем тут winapi-шные функции и try-except? try-except для своего кода, разумеется.
1.1) Вместо постоянной проверки winapi-шных функций на true бывает и Win32Check, к примеру
2) В какой Вселенной "окончание цикла обработки сообщений" означает "фактическое разрушение очереди сообщений"? Очередь жива, пока живет тред.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625113
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock...
Да, только очень грамотный программист обернёт на всякий случай вызов winapi-шных функций в try...except...
Какого класса исключения от WinApi ожидаешь? :)
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625118
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2Ерунда какая-то. Зачем в цикле очистки очереди досрочное прерывание?
Да, я тоже не понимаю, зачем, например, Борланд сделал такое в Forms.pas:
Код: pascal
1.
2.
3.
4.
5.
repeat
  Application.HandleMessage;
  if Application.FTerminate then ModalResult := mrCancel else
    if ModalResult <> 0 then CloseModal;
until ModalResult <> 0;


Василий 2если, конечно, не-gui потоку вообще возможно получение этого сообщения - но это если уже сам программер такое сделает
Да, программист такое сделает, т.к. это единственный штатный механизм окончить цикл обработки сообщений.
(Вот предыдущий пример - это не штатный, но тоже регулярно встречающийся).
Василий 2У меня на этот случай сделано такТут уже без комментариев...
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625120
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
чччДКакого класса исключения от WinApi ожидаешь? :)EPostMessageError вестимо :)
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625135
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockДа, я тоже не понимаю, зачем, например, Борланд сделал такое в Forms.pas:
Код: pascal
1.
2.
3.
4.
5.
repeat
  Application.HandleMessage;
  if Application.FTerminate then ModalResult := mrCancel else
    if ModalResult <> 0 then CloseModal;
until ModalResult <> 0;


Когда найдешь в этом коде очистку очереди сообщений не-gui потока от отправленных в очередь выделенных кусков памяти - тогда и будем разбираться, почему же это Борланд так сделал
Тут уже без комментариев...
Конечно без комментариев, раз возразить нечего.
Есть и другой вариант - с while PeekMessage(PM_REMOVE), но у меня сделано через статус, уже не помню почему.

С очередью виндовых сообщений есть один слабый момент - если запостить сообщение в момент после того, как отработает цикл очистки, но до убиения хэндла потока. Для избежания этого надо проверять Terminated перед PostMessage.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625161
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 21) При чем тут winapi-шные функции и try-except? try-except для своего кода, разумеется.
Ну так и оберни в try-except свой "... process ...", зачем всю гору.
Василий 22) В какой Вселенной "окончание цикла обработки сообщений" означает "фактическое разрушение очереди сообщений"? Очередь жива, пока живет тред.
Это не так. Во вселенной, которая называется Винда. Все сообщения, полученные после QM_QUIT, будут потеряны навсегда вместе со всеми данными (при чем PostMessage, отсылавшая их, при этом вернет True).
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625163
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2Когда найдешь в этом коде очистку очереди сообщений не-gui потока от отправленных в очередь
Это я тебе привел пример в ответ на вопрос
Василий 2Зачем в цикле очистки очереди досрочное прерывание?При чем тут очистка не понятно. Это просто, еще раз, пример "досрочного" (не дожидаясь GetMessage=False) выхода из цикла обработки сообщений.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625168
V.Borzov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2...
Неправильно выяснилось. Отправляй своему вторичному потоку тем же Post-ом, или взводи ему флаг по типу Terminated и всё. Конечно, в коде потока интервал между проверками флага (или длина очереди) д.б. небольшими, иначе отмена сработает с большой задержкой. Нет, вариант с SendMessage тоже сработает, и для простых случаев с двумя потоками он вполне приемлем

Итак, схема общения потока с основным потоком приложения (а именно этот вопрос автора топика интересовал, насколько я понял) предлагается такая:

во-первых, забить на теоретические потери памяти при postmessage и слать строки, указав ссылки на них в качестве одного из параметров. Естественно, нельзя послать ссылку на переменную типа string, объявленную в функции, а это должна быть динамически созданная pchar-строка. Удаление памяти, выделенной на строку, производится адресатом. Ну, или более сложная структура, а не просто строка, понятно. О том, что этот Postmessage не дойдет до адресата, и тот не сможет выделенную дополнительную память отпустить, не беспокоимся, это паранойя.

во-вторых, для обратной связи шлем postmessage потоку. Например, если хотим сказать ему, чтобы он закрылся. Если поток на тот момент уже самоудалился, то, собственно, не смертельно (так ли?), но вот по этой причине обращение к нему напрямую через terminate - нежелательно, если не хотим опять с блокировками зависнуть.

Все верно?
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625170
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
V.BorzovО том, что этот Postmessage не дойдет до адресата, и тот не сможет выделенную дополнительную память отпустить, не беспокоимся, это паранойя.
Да, всё верно, не беспокойся.
А если там будет не строка, а объект класса, который в деструкторе какие-то блокировки снимает, что-то закрывает, или который должен что-то в файл или базу записать - тоже абсолютно ничего страшного. Снимут процесс, добавят в базу ручками... Никто даже не удивится, ведь наверняка будут знать, что программа написана на Делфи, который мертв, и потому отнесутся с пониманием.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625176
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockНу так и оберни в try-except свой "... process ...", зачем всю гору.
Не придирайся, это наколеночный пример и к тому же это совсем не принципиально
YuRockЭто не так. Во вселенной, которая называется Винда. Все сообщения, полученные после QM_QUIT, будут потеряны навсегда вместе со всеми данными (при чем PostMessage, отсылавшая их, при этом вернет True).
Это как раз не так. То есть это "так" только в случае простейшего цикла begin while GetMessage do ... end;. Если же после цикла GetMessage выполняется цикл очистки, как я указывал, то ничего не теряется. Если хочешь, проверь сам:
В execute:
Код: pascal
1.
2.
3.
4.
5.
    while (not Terminated) and GetMessage(MsgRec, 0, 0, 0) do
      ;
   GetMessage(MsgRec, 0, 0, 0);
   if MsgRec.message = 666 then
  Ooops;


Где-то вне вторичного потока
Код: pascal
1.
2.
  PostThreadMessage(ThreadID, WM_QUIT, 0, 0);
  PostThreadMessage(ThreadID, 666, 0, 0);



YuRockЭто я тебе привел пример в ответ на вопрос
Василий 2Зачем в цикле очистки очереди досрочное прерывание?При чем тут очистка не понятно. Это просто, еще раз, пример "досрочного" (не дожидаясь GetMessage=False) выхода из цикла обработки сообщений.
Зачем мне синтетический пример досрочного выхода? Да и в любом случае, пусть эта проверка сделает Break. Потом она попадет на очистку и все закончится хэппи-эндом. В чем твое возражение-то?
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625183
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
V.Borzovво-первых, забить на теоретические потери памяти при postmessage и слать строки, указав ссылки на них в качестве одного из параметров. Естественно, нельзя послать ссылку на переменную типа string, объявленную в функции, а это должна быть динамически созданная pchar-строка.
Дело вкуса, мне например больше удобен вариант
NewStr(ps);
ps^:=strtosend;
ну и при получении - DisposeStr
автор Удаление памяти, выделенной на строку, производится адресатом.
И не забыть удалить, если PostThreadMessage вернул false.
авторО том, что этот Postmessage не дойдет до адресата, и тот не сможет выделенную дополнительную память отпустить, не беспокоимся, это паранойя.

При должном проектировании это так. По крайней мере, оппонент данного подхода до сих пор не предоставил вменяемых возражений.
авторво-вторых, для обратной связи шлем postmessage потоку. Например, если хотим сказать ему, чтобы он закрылся. Если поток на тот момент уже самоудалился, то, собственно, не смертельно (так ли?)
Конечно не смертельно, PostThreadMessage вернет false и по GetLastError = ERROR_INVALID_THREAD_ID можно будет понять, что он уже помер.
автор, но вот по этой причине обращение к нему напрямую через terminate - нежелательно, если не хотим опять с блокировками зависнуть.

Ничего страшного, если только тред не FreeOnTerminate. terminate просто ставит булевское поле terminated в true и никого не блокирует
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625189
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2
Код: pascal
1.
PostThreadMessage(ThreadID, WM_QUIT, 0, 0);


А PostQuitMessage тебе встречать не приходилось? Ну да ладно.
Василий 2Если же после цикла GetMessage выполняется цикл очистки
Давай про цикл очистки не будем, просто вообще, ну не смешно.
Василий 2проверь самКак раз проверил и нашел интересный нюанс. Опровергающий один (только один) из моих примеров, когда сообщения могут остаться необработанными.
Оказывается (вполне вероятно, что это недавно Майкрософт запилил так - раньше я такого поведения не помню), что после PostQuitMessage в GetMessage не приходит WM_QUIT, пока очередь сообщений не станет пуста (именно пуста). А после него - в PostMessage возвращается ошибка.
Т.ч. да - если GetMessage вернул 0 - да, то PostMessage больше не сработает, тут я был неправ.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625199
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockА PostQuitMessage тебе встречать не приходилось? Ну да ладно.
А покажи-ка мне, как через PostQuitMessage послать WM_QUIT другому потоку
авторДавай про цикл очистки не будем, просто вообще, ну не смешно.
Замять тему, когда возразить нечего? Достойный ход, да.
Василий 2Опровергающий один (только один) из моих примеров, когда сообщения могут остаться необработанными.
Из двух примеров один опровергся, а другой насквозь надуман :D
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625202
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2Из двух примеров один опровергся, а другой насквозь надуман :D
1. Заметь, опровергся мной, а не тобой, который советовал и продолжает советовать какие-то бредовые "циклы очистки" для разрушенной, закрытой очереди.
2. Ты меня спросил: "зачем искусственно прерывать цикл?" Я ответил, что так может быть построена логика программы (и циклы при этом могут быть чужими, в которые не удастся наставить костылей). Привел пример. Он тебе не понравился. Если ты думаешь, что я буду шарашить тебе примеры, пока хоть один из них тебя не "устроит" - ты ошибаешься.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625203
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2Замять тему, когда возразить нечего? Достойный ход, да.Ок, хорошо, я во всем не прав. Используй "циклы очистки" и дальше. Только другим советовать не надо нафантазированный бред.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625398
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock1. Заметь, опровергся мной, а не тобой, который советовал и продолжает советовать какие-то бредовые "циклы очистки" для разрушенной, закрытой очереди.
1. Доказательства того, что внутри Execute очередь может разрушиться от прихода WM_QUIT, будут (для буквоедов: TerminateThread не рассматривается)? Без доказательств бред - это как раз то, что утверждаешь ты.
2. Твоё опровержение играет малую роль, даже если бы поведение функций было прежним, твой пример все равно бы не сыграл (для буквоедов: рассматриваем цикл очистки второго варианта, с GetQueueStatus).
3. Я всё ещё жду примера, как через PostQuitMessage отправить WM_QUIT другому потоку
автор2. Ты меня спросил: "зачем искусственно прерывать цикл?" Я ответил, что так может быть построена логика программы (и циклы при этом могут быть чужими, в которые не удастся наставить костылей). Привел пример. Он тебе не понравился. Если ты думаешь, что я буду шарашить тебе примеры, пока хоть один из них тебя не "устроит" - ты ошибаешься.

Вообще не в кассу. Я тебя спросил, где в цикле вычерпывания присланных сообщений при завершении потока может встретиться необходимость искусственного прерывания. Ты так ничего и не ответил. Только замечание с окончанием цикла GetMessage по приходу WM_QUIT было корректным, но и то в моем коде это давно предусмотрено, здесь же кусок был написан на коленке.

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

То, что механизм очистки очереди сообщений не влезает в твой разум - это твои личные трудности, на которые мне начхать. Но не надо выдавать свою некомпетентность за признанные истины - новички могут принять за чистую монету, и дурь размножится. А ее и так хватает.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625402
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати, несмотря на хамлоидность, ты натолкнул меня на соображение насчет сообщений, присланных в момент после очистки очереди и до разрушения потока. За это спасибка.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39625416
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2Доказательства того, что внутри Execute очередь может разрушиться от прихода WM_QUIT, будут (для буквоедов: TerminateThread не рассматривается)? Без доказательств бред - это как раз то, что утверждаешь ты.Доказательства - это код Майкрософт. В интернете его полно, ищи и разбирайся. Я же руководствуюсь документацией и поведением функций, замеченным в результате опыта использования.
Да, после обработки WM_QUIT очередь закрыта для использования, и даже возобновить ее сначала не удастся.
Зачем ты сюда втянул TerminateThread, для меня тайна.
Василий 2Я всё ещё жду примера, как через PostQuitMessage отправить WM_QUIT другому потокуЖди. С таким же успехом можешь подождать, пока я тебе котлет нажарю. Я нигде не говорил, что такое возможно, даже думал, что такое в голову прийти может.

Василий 2Я тебя спросил, где в цикле вычерпывания присланных сообщений при завершении потока может встретиться необходимость искусственного прерывания. Ты так ничего и не ответил.Очередная лож. Я тебе ответил в 1-м же ответе: там, где встретится такая необходимость с точки зрения логики работы программы - флаг какой-то взвелся - прерываем очередь и всё, до свидания.
Василий 2не надо выдавать свою некомпетентность за признанные истины - новички могут принять за чистую монету, и дурь размножится. А ее и так хватает.Да, да, я уже писал, что с тобой полностью во всём согласен.
Дообрабатывай очередь и дальше после ее закрытия. И не забывай, как ты грамотно советовал, проверять на not Terminated перед PostThreadMessage - это тоже наверняка сделает код более грамотным и надежным.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39626230
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ох, такое ощущение, что пытаешься религиозному фанатику времен раннего средневековья объяснить теорию эволюции... всё то же самое - полная уверенность в непогрешимости собственных доводов, отсутствие каких-либо доказательств, избирательная глухота на самые неудобные доводы оппонента и перевирание остальных. Подобная беседа совершенно бессмысленна и лишь пустая трата усилий. Тем не менее, надо признать, в процессе всё же удалось набрести на полезные соображения, хоть это и не заслуга YuRock. На всю понаписанную им чушь отвечать не буду, это как об стену горох, возьму только упорно культивируемую им концепцию "разрушения очереди сообщений".

Итак:
YuRockДа, после обработки WM_QUIT очередь закрыта для использования, и даже возобновить ее сначала не удастся.
Вот
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TForm2 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TMsgLoopThread = class(TThread)
    procedure Execute; override;
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

{ TMsgLoopThread }

const
  MSG_SUICIDE = WM_APP+1;

procedure TMsgLoopThread.Execute;
var
  MsgRec: TMsg;
  Counter: Integer;
begin
  PeekMessage(MsgRec, 0, 0, 0, PM_NOREMOVE);

  repeat
    Counter := 0;

    while GetMessage(MsgRec, 0, 0, 0) do
      if MsgRec.message = MSG_SUICIDE then
        PostQuitMessage(1) // Для тех, кто считает PostQuitMessage <> PostThreadMessage(WM_QUIT)
      else
        Inc(Counter);

    OutputDebugString(PChar('WM_QUIT received but we''re still alive! Got messages: '+IntToStr(Counter)));
  until False;

  OutputDebugString('Thread finished');
end;

procedure TForm2.FormCreate(Sender: TObject);
var
  th: TMsgLoopThread;
  i: Integer;
begin
  th := TMsgLoopThread.Create(False);
  Sleep(2000); // даем системе создать очередь для потока, самый тупой способ чисто для примера
  repeat
    // кидаем в очередь обычные сообщения
    for i := 1 to 10 do
      if not PostThreadMessage(th.ThreadID, WM_APP+100, 0, 0) then
        RaiseLastOSError;
    // командуем потоку "самоубиться", послав себе WM_QUIT
    // исключительно для фанатиков PostQuitMessage
    if not PostThreadMessage(th.ThreadID, MSG_SUICIDE, 0, 0) then
      RaiseLastOSError;
    // сообщаем юзеру и заодно даем потоку отработать WM_QUIT
    ShowMessage('Press to continue');
    // ВНЕЗАПНО! поток по-прежнему живой, что выяснится на следующей итерации
  until False;

  ShowMessage('Thread finished');
end;

end.


Запусти и нажимай на кнопки. После того, как получишь сообщение 'Thread finished', можешь возвращаться xD. Только мышку не протри xD
Наверняка последует заявление, что код написан криво, пробелы расставлены не так и использовать Функцию_X может только полный нуб, в глаза не видевший MSDN и прочая лабуда, но вдруг попадем на редкий момент просветления.

Так, с шелухой разобрались, теперь к полезному - вдруг кто-то придет сюда из поиска и доберется до этого поста.
Организация Execute потока, к которой я пришел, такова:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
procedure TMsgLoopThread.Execute;

  procedure ProcessMsg(const MsgRec: TMsg; Terminating: Boolean);
  begin
    // обрабатывает сообщения, если Terminating = False, и **в любом случае** удаляет
    // переданные в сообщении динамические объекты, если есть
  end;

begin
    ...
    // Цикл выборки сообщений плюс проверка, не завершён ли поток.
    // Если сработает Terminated - оставшиеся в очереди сообщения будут извлечены
    //   из очереди ниже, в блоке очистки
    // Если сработает GetMessage - получен WM_QUIT, никак не обрабатываем его
    while not Terminated do
      if GetMessage(MsgRec, 0, 0, 0) then
        ProcessMsg(MsgRec, False)
      else
      begin
         // для целостности, а также для исключения возможности утечки (см. ниже п.3)
         Terminate;
         Break;
      end;

    // вычерпываем все сообщения из очереди и удаляем все выделенные куски
    while PeekMessage(MsgRec, 0, 0, 0, PM_REMOVE) do
      ProcessMsg(MsgRec, True);

end;



1. Поток можно завершить как послав сообщение (PostThreadMessage(WM_QUIT)), так и через Terminate.
2. При завершении через Terminate надо обязательно послать "сигнальное" сообщение, т.к. поток может зависнуть на GetMessage, если его очередь будет пуста
3. Нюанс: есть вероятность пропажи сообщений, если они будут отправлены в период между последним ProcessMsg и разрушением потока (ExitThread). Для избежания этого надо убедиться, что Terminated потоку не будут отправляться сообщения - к примеру, можно вообще закрыть ThreadID от доступа извне, вместо него добавив метод PostMessage, который будет проверять флаг Terminated. Разумеется, это не относится к "сигнальному" сообщению из п.2 - его слать нужно в любом случае.
4. Используемая мной ранее функция GetQueueStatus оказалась вещью в себе, вопреки описанию (весьма туманному, кстати) выдающей странные результаты. Например, она может вернуть <>0 при пустой очереди. Поэтому я заменил ее на PeekMessage, которая с такими параметрами идеальна для задачи очистки.
5. Схема Execute, разумеется не фиксирована - можно добавлять try-except в зависимости от задачи, вместо ProcessMsg можно сделать обработку в основном цикле, а чисто удаление выделить в отдельную FreeMsgData и т.д.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39626318
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2Запусти и нажимай на кнопки. После того, как получишь сообщение 'Thread finished', можешь возвращаться xD
О, ты молодец :)
Нашёл случайно еще один момент, в котором я немного ошибался: да, действительно, после обработки WM_QUIT теоретически еще можно иногда дождаться сообщений с помощью повторного цикла GetMessage.
Разумеется, только в том случае, если WM_QUIT был послан только один раз.
Замени вот это
Василий 2
Код: pascal
1.
2.
if MsgRec.message = MSG_SUICIDE then
        PostQuitMessage(1) // Для тех, кто считает PostQuitMessage <> PostThreadMessage(WM_QUIT)


на это
Код: pascal
1.
2.
3.
4.
  if MsgRec.message = MSG_SUICIDE then begin
    PostThreadMessage( ThreadId, WM_QUIT, 0, 0 ); // Да, PostQuitMessage <> PostThreadMessage(WM_QUIT). C PostQuitMessage такое не сработает. Но ты сам говорил: "а как же послать из другого потока?" ))
    PostThreadMessage( ThreadId, WM_QUIT, 0, 0 ); // Да, PostQuitMessage <> PostThreadMessage(WM_QUIT). C PostQuitMessage такое не сработает. Но ты сам говорил: "а как же послать из другого потока?" ))
  end;


И увидишь, как неожиданно для тебя начнет работать твой пример.
Василий 2 Наверняка последует заявление, что код написан криво
Василий 2
Код: pascal
1.
2.
    // вычерпываем все сообщения из очереди и удаляем все выделенные куски
    while PeekMessage(MsgRec, 0, 0, 0, PM_REMOVE) do


Как красиво и грамотно заставлять поток работать еще неизвестное количество времени после Terminate. Для тех, кто "придет сюда из поиска и доберется до этого поста": не надо использовать эту шелуху. Ваши потоки всегда должны адекватно реагировать на команду "закрыться", а не висеть еще неизвестно сколько.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39626964
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockНашёл случайно еще один момент, в котором я немного ошибался: да, действительно, после обработки WM_QUIT теоретически еще можно иногда дождаться сообщений с помощью повторного цикла GetMessage.
Разумеется, только в том случае, если WM_QUIT был послан только один раз.
*фейспалм* случайно, теоретически, иногда дождаться... тут программирование или гадание на кофейной гуще?
Ты вообще осознал суть примера? Она в том, что ловить GetMessage-ом WM_QUIT можно сколько угодно раз, ничего с очередью от прихода этого сообщения не делается.
Можешь закомментить вот эти строки
Код: pascal
1.
2.
3.
//    for i := 1 to 10 do
//      if not PostThreadMessage(th.ThreadID, WM_APP+100, 0, 0) then
//        RaiseLastOSError;


и пожалуйста, бесконечная отправка WM_QUIT потоку без каких-либо последствий.

YuRockЗамени вот это
...
И увидишь, как неожиданно для тебя начнет работать твой пример.
Заменил. Всё циклится. В выхлопе данные строки:
Debug Output: WM_QUIT received but we're still alive! Got messages: 10 Process Project3.exe (6112) - получили первый WM_QUIT
Debug Output: Cleanup done: message count 1 Process Project3.exe (6112) - съели второй WM_QUIT
Всё ожидаемо. Где удивляться?

YuRockКак красиво и грамотно заставлять поток работать еще неизвестное количество времени после Terminate. Для тех, кто "придет сюда из поиска и доберется до этого поста": не надо использовать эту шелуху. Ваши потоки всегда должны адекватно реагировать на команду "закрыться", а не висеть еще неизвестно сколько.
Теперь я окончательно убедился, что ты существуешь в какой-то иной реальности, где плюшевые единорожки едят радугу.
Во-первых, поток по определению делает что-то продолжительное, он может висеть на ожидании любой синхронной операции либо выполнять суровые вычисления, и команда "закрыться" ему будет сугубо побоку, пока он не доделает задачу. Так что всегда надо закладываться на "неизвестное количество времени после Terminate".
Во-вторых, в данном случае "неизвестное количество времени" - это максимум (T_call + T_case + T_FreeMem)*10000. Это всё занимает десятки миллисекунд. Конечно, есть системы, где и это играет роль, но в них явно не будут создавать и удалять по сотне потоков в секунду. Единственный вариант, когда завершение может затянуться - это если после Terminate потоку продолжают сыпать сообщения, причем с огромной скоростью, сравнимой с (T_call + T_case + T_FreeMem). Но это фича метода, и я указал, как такое предотвратить.
В общем, довод мимо. Этак можно догнаться до того, что программа, дескать, слишком долго закрывается из-за сохранения файла конфигурации - а ну его к черту, юзер в следующий раз заново настроит, ничего с ним не сделается.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39626977
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2Всё ожидаемо. Где удивляться?Там, где "Got messages:" не подряд идут.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39626978
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2Во-первых, поток по определению делает что-то продолжительное, он может висеть на ожидании любой синхронной операции либо выполнять суровые вычисления, и команда "закрыться" ему будет сугубо побоку, пока он не доделает задачу.К счастью, у меня таких потоков не бывает.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39626984
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2в данном случае "неизвестное количество времени" - это максимум (T_call + T_case + T_FreeMem)*10000. Это всё занимает десятки миллисекундОткуда ты знаешь, что будут делать и как работать потоки других людей?
Ты же советуешь другим этот подход. И тут может понадобиться не только освобождение памяти, а что угодно.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39626987
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2тут программирование или гадание на кофейной гуще?Гадание всегда начинается там, где программа перестает ожидаемо (даже для пользователя) работать.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39626994
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если хочешь надежности и предсказуемости кода лучше все делать самому.
...
Рейтинг: 0 / 0
отправить сообщение "главному потоку" из "дочернего"
    #39627022
V.Borzov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2,

Да, использование Postmessage для уведомления главного окна, когда передаваемые структуры или просто строки удаляются получателем, а осуществление обратной связи с помощью PostThreadMessage, сделало поток гораздо более самостоятельным, и там, где основной поток занимается какими-то своими делами, наш поток не висит, а продолжает работу. Отсюда и общее ускорение. Насколько я понял, если поток или объект получил сообщение, то это значит, что он получил и все предыдущие, они не ушли куда-то в никуда. А если есть опасность потери оставшихся, то этот вопрос можно решать.
...
Рейтинг: 0 / 0
77 сообщений из 77, показаны все 4 страниц
Форумы / Delphi [игнор отключен] [закрыт для гостей] / отправить сообщение "главному потоку" из "дочернего"
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]