Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Callback из потока / 23 сообщений из 23, страница 1 из 1
30.09.2018, 16:55
    #39710565
Kast2K
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Callback из потока
Добрый день, коллеги!

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

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

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

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

Хотя, я предпочел postmessage.
...
Рейтинг: 0 / 0
30.09.2018, 23:31
    #39710683
Кроик Семён
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Callback из потока
А можно в TThreadList поместить данные
И отправить тем же PostMessage'ем сообщение с индексом в списке
...
Рейтинг: 0 / 0
01.10.2018, 09:57
    #39710775
Kast2K
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Callback из потока
Соколинский Борис Мы ему поможем - расскажем о 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
01.10.2018, 10:10
    #39710783
Kast2K
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Callback из потока
Да и микрософт говорит, что данная функция не должна ничего возвращать
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
01.10.2018, 11:07
    #39710807
Dimonka
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Callback из потока
Кроме сообщений можно ещё событие (Event) выставлять. Установлено событие - есть новые данные. Считал данные, сбросил событие. Уснул до нового события.
...
Рейтинг: 0 / 0
01.10.2018, 11:28
    #39710821
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Callback из потока
DimonkaКроме сообщений можно ещё событие (Event) выставлять. Установлено событие - есть новые данные. Считал данные, сбросил событие. Уснул до нового события.
Это в поток, а не из него.
...
Рейтинг: 0 / 0
01.10.2018, 11:43
    #39710835
Kast2K
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Callback из потока
C ошибкой разобрался - процедуру изначально засунул в private и компилятор ругался.
SendMessageCallBack работает, данные приходят, но в процедуру SMCB ничего не возвращается, т.к. она в потоке.

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

Ну и назачем эти прыжки в ширину, если результат можно прямо вернуть при вызове SendMessage?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
01.10.2018, 18:10
    #39711167
Соколинский Борис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Callback из потока
Dimitry Sibiryakov,
предлагаю обмен очевидными репликами пропустить, никакого конструктива из этой дискуссии не выйдет.
...
Рейтинг: 0 / 0
02.10.2018, 07:46
    #39711409
Kast2K
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Callback из потока
Соколинский Борис 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
02.10.2018, 12:47
    #39711592
Dimonka
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Callback из потока
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
02.10.2018, 12:54
    #39711603
Соколинский Борис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Callback из потока
Dimonka,
Это же из потоковой процедуры. Там без разницы, какие параметры задавать, главное чтобы винда поняла, что поток готов к обработке callback-а
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Callback из потока / 23 сообщений из 23, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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