Перейти к содержанию
Fire Monkey от А до Я
  • 0

Аналог Post в FMX android


krapotkin

Вопрос

представим обработчик TEdit.OnChange. Он запускает сложный поток действий, который, в том числе, может привести к изменению Edit и повторному входу в OnChange.

Для избегания подобных проблем в Windows вместо изменения Edit.Text можно было послать сообщение, обработчик которого тоже изменит Edit.text, но уже после выхода из OnChange.

 

Как сделать такой финт в андроид, ведь PostMessage нет? подойдет ли на эту роль SendMessage?

Ссылка на комментарий

Рекомендуемые сообщения

  • 0

queue элегантнее

 

столкнулся с проблемой, когда реализовал TEdit с автозавершением из интернета

все работало хорошо, пока не начал делать кэширование. Когда запрос новый, запустили тред, он вернется и все сам сделает.

А если запрос уже был, можно подставлять прямо из кэша, но тут же срабатывает onChange опять, так что всяко придется тред запускать.

Ссылка на комментарий
  • 0

В дополнение: если мне не изменяет память, то обработка всех queued-методов производится (если продолжаем разговор в терминах Windows) ДО обработки всех сообщений.

Т.е. если вы сделаете (к примеру):

PostMessage(...)
TThread.Queue(...)

то код в queue будет выполнен раньше, чем обработка WM_ из PostMessage.

Уж не помню, где это я на такое напоролся, но дело было в iOS :)

Ссылка на комментарий
  • 0
  • Администраторы

С моей точки зрения, метод TThread.Queue имеет один весомый недостаток. А именно:

  • Если вызов метода TThread.Queue идет в главном потоке, то код будет вызыван немедленно.
class procedure TThread.Queue(const AThread: TThread; AMethod: TThreadMethod);
var
  LSynchronize: PSynchronizeRecord;
begin
  if AThread <> nil then
    AThread.Queue(AMethod)
  else
  begin
    New(LSynchronize);
    try
      LSynchronize.FThread := nil;
      LSynchronize.FSynchronizeException := nil;
      LSynchronize.FMethod := AMethod;
      Synchronize(LSynchronize, True); // <-- Смотрим сюда
    finally
      if MainThreadID = CurrentThread.ThreadID then
        Dispose(LSynchronize);
    end;
  end;
end;

А потом на кусочек этого кода:

class procedure TThread.Synchronize(ASyncRec: PSynchronizeRecord; QueueEvent: Boolean = False);
var
  SyncProc: TSyncProc;
  SyncProcPtr: PSyncProc;
begin
  if CurrentThread.ThreadID = MainThreadID then
  begin
    if Assigned(ASyncRec.FMethod) then
      ASyncRec.FMethod()
    else if Assigned(ASyncRec.FProcedure) then
      ASyncRec.FProcedure();
  end else

Из реализации метода Synchronize, как раз и видно, что код будет вызван немедленно, если текущий тред - это главный поток. 

 

Итог

  • TThread.Queue заменяет PostMessage, если вызов идет не из главного потока.
  • Если вызов TThread.Queue идет из главного потока, то это равносильно прямому вызову процедуры или метода.

 

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...