powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / отправить сообщение "главному потоку" из "дочернего"
25 сообщений из 77, страница 3 из 4
отправить сообщение "главному потоку" из "дочернего"
    #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
25 сообщений из 77, страница 3 из 4
Форумы / Delphi [игнор отключен] [закрыт для гостей] / отправить сообщение "главному потоку" из "дочернего"
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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