powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Callback из потока
23 сообщений из 23, страница 1 из 1
Callback из потока
    #39710565
Фотография Kast2K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день, коллеги!

Есть поток, который берет данные из базы и форма, которая должна принимать эти данные.

глобальный тип
Код: pascal
1.
2.
3.
4.
5.
  TToolData=record
    Passed      : Boolean;
    IDBody      : Integer;   
    ...
  end;



Ранее поток писал в TList, а форма считывала из него по таймеру.
Код: 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.
type
  TSelectPointsThread = class(TThread)
....
procedure TSelectPointsThread.ProduceQuery;
var
  WT:TToolData;
begin
  CoInitialize(nil);
  try
    try
....
      adsp.Open;

      if adsp.RecordCount>0 then
        begin
          while not adsp.Eof do
            begin
              WT:=default(TToolData);

              //распихиваю принятые данные в record...
              
              //старый вариант
              ToolsList.Lock;
              ToolsList.AddData(WT);
              ToolsList.Unlock;

              adsp.Next; 
            end;
        end;
    except
      //
    end;
  finally
    CoUninitialize;
  end;



Задумав избавиться от Timer реализовал CallBack функцию, но получается что она работает асинхронно и часть данных теряется, т.е. приходит мусор.

Код: 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.
type
  TSWPCallback = procedure(const WT:TToolData) of object;

  TSelectPointsThread = class(TThread)
....
procedure TSelectPointsThread.ProduceQuery;
var
  WT:TToolData;
begin
  CoInitialize(nil);
  try
    try
....
      adsp.Open;

      if adsp.RecordCount>0 then
        begin
          while not adsp.Eof do
            begin
              WT:=default(TToolData);

              //распихиваю принятые данные в record...
              
              //реализация c CallBack
              if not Assigned(FSWPCallback) then
                Exit;

              Self.Queue( 
                          procedure
                          begin
                            FSWPCallback(WT);
                          end
                        );

              adsp.Next; //приходит более 1 строки 
            end;
        end;
    except
      on e:Exception do
      begin
        PostToLog('SelectCarErrorsOnMonitoredStations error='+e.Message);
      end;
      on e:EOleException do
      begin
        PostToLog('SelectCarErrorsOnMonitoredStations OLE error='+e.Message);
      end;
    end;
  finally
    CoUninitialize;
  end;


Форма
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
procedure TfrmMain.SelectPointsCallback(const WTD: TToolData);
var
  WT:TTool;
begin
      WT:=TTool.Create;
      WT.AddToolData(WTD); //тут вижу одни и те же данные
      WrongTools.Add(WT);
end;



Не могли бы вы подсказать, как реализовать данное решение правильно? Может CallBack и не подходит вовсе...
Или надо сначала получить все данные, а потом их в Callback заслать массивом?

Спасибо за разъяснения! :)
...
Рейтинг: 0 / 0
Callback из потока
    #39710570
Фотография Kast2K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Отбой,
надо было читать больше и глубже :)
Решение
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
В потоке переменную WT вынес в private
создал процедуру
procedure MyCallBack;
begin
if Assigned(FSWPCallback) then
  FSWPCallback(WT);
end;

// в исполняемой процедуре указал 

          while not adsp.Eof do
            begin

              Synchronize(MyCallBack); // Remy Lebeau

              adsp.Next;
            end;



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

PS. Жалко нельзя свои же темы удалять.
...
Рейтинг: 0 / 0
Callback из потока
    #39710571
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kast2K,
передавай из потока сообщения главному окну. Можно как синхронно, так и асинхронно.
...
Рейтинг: 0 / 0
Callback из потока
    #39710574
Фотография Kast2K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Соколинский Борис,
О WM_Copydata я тоже думал, но захотел попробовать так для начала :)
...
Рейтинг: 0 / 0
Callback из потока
    #39710577
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kast2K,
WM_CopyData нужен для обмена данными между разными процессами.
Просто сделай custom-сообщение (WM_USER+xxx) и отправляй из потока. Synchronize - не лучшее решение, если главный поток чем-то занят, дополнительный будет ждать.
...
Рейтинг: 0 / 0
Callback из потока
    #39710585
чччД__
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
+1 к предложению использовать сообщения.
И можно сразу ссылку на данные передавать, никакой синхронизации не потребуется, только не забывать ресурсы (блок данных или объект) освобождать на стороне приема.
...
Рейтинг: 0 / 0
Callback из потока
    #39710586
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Соколинский БорисПросто сделай custom-сообщение (WM_USER+xxx) и отправляй из потока. Synchronize - не
лучшее решение, если главный поток чем-то занят, дополнительный будет ждать.
Вот тут мне любопытно, на какие из двух граблей аффтар наступит:
1) Будет посылать SendMessage в главный поток, который чем-то занят (что само по себе
плохой дизайн ибо единственное, чем должен быть занять главный поток это как раз обработка
сообщений);
2) Будет посылать PostMessage, но, будучи не в курсе управления памятью, будет ловить
ошибки обращения к уже освобождённой памяти и/или "мусор".
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Callback из потока
    #39710591
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakovединственное, чем должен быть занять главный поток это как раз обработка... Вот он как раз и может быть занят обработкой сообщений. А обработка может быть длительной.

Dimitry Sibiryakov2) Будет посылать PostMessage, но, будучи не в курсе управления памятью, будет ловить
ошибки обращения к уже освобождённой памяти и/или "мусор". Мы ему поможем - расскажем о SendMessageCallback.
...
Рейтинг: 0 / 0
Callback из потока
    #39710598
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Соколинский БорисА обработка может быть длительной.

Может в неправильных руках. Но не должна.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Callback из потока
    #39710600
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovМожет в неправильных руках. Но не должна. Не согласен.
Все, что связано с отрисовкой может быть длительным. А вне основного потока, в силу особенностей реализации дельфей будет очень глюкаво.
...
Рейтинг: 0 / 0
Callback из потока
    #39710678
V.Borzov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Соколинский Борис Не согласен.
Все, что связано с отрисовкой может быть длительным. А вне основного потока, в силу особенностей реализации дельфей будет очень глюкаво.
А не надо блокировать объект (или стэк), откуда берешь данные для отрисовки, на всё время отрисовки. Заблокировал объект, чтобы туда никто ничего не писал, считал данные, дальше разблокируй объект и рисуй себе эти данные сколько угодно. Объект( или стэк) же будет в это время заполняться новыми данными.

Хотя, я предпочел postmessage.
...
Рейтинг: 0 / 0
Callback из потока
    #39710683
Фотография Кроик Семён
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А можно в TThreadList поместить данные
И отправить тем же PostMessage'ем сообщение с индексом в списке
...
Рейтинг: 0 / 0
Callback из потока
    #39710775
Фотография Kast2K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Соколинский Борис Мы ему поможем - расскажем о SendMessageCallback.
Решил поэкспериментировать, но что-то идет не так.

реализовал процедуру обратного вызова на основании http://winapi.freetechsecrets.com/win32/WIN32SendAsyncProc.htm
Код: pascal
1.
procedure SMCB(Window: HWND; Msg: UINT; Data: DWORD;LResult: LRESULT); stdcall;


создал сообщение WM_USER+1024;

пытаюсь скопмилировать и получаю ошибку
Код: pascal
1.
2.
3.
4.
5.
6.
      SendMessageCallback(Application.MainFormHandle,
        MyMsg,
        0,
        LParam(@lst[i]),
        @SMCB, //ошибка [dcc32 Error] : E2036 Variable required
        1);


В книге (правда устаревшей уже) указано также
https://ru.scribd.com/doc/53597660/The-Tomes-of-Delphi-Win32-Core-API-Windows-2000-Edition
...
Рейтинг: 0 / 0
Callback из потока
    #39710783
Фотография Kast2K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да и микрософт говорит, что данная функция не должна ничего возвращать
Return Value

This callback function does not return a value.

https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nc-winuser-sendasyncproc
...
Рейтинг: 0 / 0
Callback из потока
    #39710807
Фотография Dimonka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кроме сообщений можно ещё событие (Event) выставлять. Установлено событие - есть новые данные. Считал данные, сбросил событие. Уснул до нового события.
...
Рейтинг: 0 / 0
Callback из потока
    #39710821
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DimonkaКроме сообщений можно ещё событие (Event) выставлять. Установлено событие - есть новые данные. Считал данные, сбросил событие. Уснул до нового события.
Это в поток, а не из него.
...
Рейтинг: 0 / 0
Callback из потока
    #39710835
Фотография Kast2K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
C ошибкой разобрался - процедуру изначально засунул в private и компилятор ругался.
SendMessageCallBack работает, данные приходят, но в процедуру SMCB ничего не возвращается, т.к. она в потоке.

Спасибо за помощь!
...
Рейтинг: 0 / 0
Callback из потока
    #39711104
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kast2KSendMessageCallBack работает, данные приходят, но в процедуру SMCB ничего не возвращается, т.к. она в потоке. Это неважно.
СallBack будет обработан если в потоке будет запускаться проверка сообщений. GetMessage() вставляй периодически.
...
Рейтинг: 0 / 0
Callback из потока
    #39711123
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Соколинский БорисСallBack будет обработан если в потоке будет запускаться проверка сообщений. GetMessage()
вставляй периодически.

Ну и назачем эти прыжки в ширину, если результат можно прямо вернуть при вызове SendMessage?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Callback из потока
    #39711167
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,
предлагаю обмен очевидными репликами пропустить, никакого конструктива из этой дискуссии не выйдет.
...
Рейтинг: 0 / 0
Callback из потока
    #39711409
Фотография Kast2K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Соколинский Борис GetMessage() вставляй периодически.
Спасибо за подсказку!
Решилось
Код: pascal
1.
2.
3.
4.
5.
6.
7.
var
   FMSG : TMsg;
begin
    repeat
       PeekMessage(FMSG,Application.MainFormHandle, 0, 0, PM_NOREMOVE);
   ....
    until Terminated
...
Рейтинг: 0 / 0
Callback из потока
    #39711592
Фотография Dimonka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kast2KСоколинский Борис GetMessage() вставляй периодически.
Спасибо за подсказку!
Решилось
Код: pascal
1.
2.
3.
4.
5.
6.
7.
var
   FMSG : TMsg;
begin
    repeat
       PeekMessage(FMSG,Application.MainFormHandle, 0, 0, PM_NOREMOVE);
   ....
    until Terminated


Странный подход, ну да ладно.
А чем элементарная реакция на сообщение не устраивает?
Код: pascal
1.
2.
3.
  TForm1 = class(TForm)
  private
    procedure OnMySuperDuperMessage(var Msg: TMessage); message WM_MySuperDuperMessage;
...
Рейтинг: 0 / 0
Callback из потока
    #39711603
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimonka,
Это же из потоковой процедуры. Там без разницы, какие параметры задавать, главное чтобы винда поняла, что поток готов к обработке callback-а
...
Рейтинг: 0 / 0
23 сообщений из 23, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Callback из потока
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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