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

Приложение не отвечает. Закрыть?


Steepe_Hare

Вопрос

На Android-е мое приложение иногда делает определенную вычислительную работу и в этот момент не реагирует на нажатия. Application.ProcessMessages не помогает. Потом появляется это сообщение ("Приложение не отвечает. Закрыть?") Если подождать пока отработает, то всё возвращается в норму.

Слышал, что нужно вычисления выносить в поток TThread.

Но Бога ради, объясните тупому на простых примерах, как им пользоваться? Чувствую, что там хватает подводных камней и неожиданных результатов в вычислениях.

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

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

  • 0
  • Модераторы

ну так и вы не дали код, что у вас там происходит я незнаю.

а там представлен шаблон с комментариями

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

«Самое худшее, что может случиться с отзывчивостью вашего приложения это диалог "Приложение не отвечает" (ANR)

Здесь описан механизм работы с зависанием UI, и как с этим бороться.

На русском пока нет, но, если нужно, гугл переводчик подскажет.

Ссылка на комментарий
  • 0
В 28.11.2016 в 22:39, ZuBy сказал:

ну так и вы не дали код, что у вас там происходит я незнаю.

а там представлен шаблон с комментариями

Взгляните, пожалуйста, на этот простой пример. Под Виндами работает отлично, под Андроидом зависает.

Proj.zip

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

Увы, но использовать ProcessMessage дурной тон... Именно он и даёт зависание главного треда.

Ссылка на комментарий
  • 0
55 минут назад, Brovin Yaroslav сказал:

Увы, но использовать ProcessMessage дурной тон... Именно он и даёт зависание главного треда.

Не знал этого, всегда пользуюсь ProcessMessages для обновления состояния контролов на форме. А какой код будет хорошим тоном?

 

Ссылка на комментарий
  • 0
  • Модераторы
5 часов назад, Pax Beach сказал:

Не знал этого, всегда пользуюсь ProcessMessages для обновления состояния контролов на форме. А какой код будет хорошим тоном?

строить логику так, чтобы все обновлялось самостоятельно

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

Подскажите плиз, как переписать данный простой код под Андроид, чтобы сохранился функционал и программа не зависла. Видимо, использовать TThread?

Изменено пользователем Steepe_Hare
Ссылка на комментарий
  • 0

еще хотелось бы знать, а что нужно-то ? из вашего кода не ясно

запустить поток, активировать кнопку Button2 чтобы она остановила поток?

либо выполнять какое-то действие время от времени, а по Button2 прекратить его выполнять?

тогда простой таймер вполне решает вопрос

Ссылка на комментарий
  • 0
  • Модераторы
4 минуты назад, Steepe_Hare сказал:

нужно именно дождаться от пользователя ответа (5 раз нажатий на Button2), а до той поры ничего не делать

Вам дали ответ

9 минут назад, krapotkin сказал:

тогда простой таймер вполне решает вопрос

 

Ссылка на комментарий
  • 0
29 минут назад, krapotkin сказал:

а если до нажатия 5 раз ничего делать не надо, то и таймер лишний )))

"ничего не надо делать" - имеется в виду "не выполнять код после того, как Finish стало True"

Задача: дождаться действий пользователя (допустим, 5 раз нажать на Button2) и только потом выполнять следующий после этого код
 
 while not Finish do
    Application.ProcessMessages;

Изменено пользователем Steepe_Hare
Ссылка на комментарий
  • 0

Нужно сделать так:

Процедура ();

Начало цикла:

выполняется код

....

ждем определенной реакции пользователя

....

выполняется код

возврат в начало цикла

Ссылка на комментарий
  • 0
  • Администраторы
10 часов назад, Pax Beach сказал:

А какой код будет хорошим тоном?

Асинхронный. Он в какой-то степени сложнее. Но зато не будет проблем в будущем.

Например, на андроиде в принципе нету возможности обрабатывать сообщения из очереди, как это все привыкли делать в WIndows, ProcessMessage. Этот код приватный и закрытый.

Для определения реакции пользователя. Лучше сделать класс, который будет являться надстройкой над обычными событиями компонентов.

Например, вы хотите дождаться 5 нажатий на кнопку от пользователя. Вы определяете свой класс с набором обработчиков событий. Типа ButtonClickHandler и другие, если нужны. В нем просто считаете количество нажатий. И при достижении условия (счетчик нажатий равен пяти), генерируете своё событие: OnClicked5Times.

Достоинства такого подхода:

  1. вы выносите логику из кода формы. 
  2. Сможете использовать ваш класс в других местах.
  3. Получится асинхронный вариант, не использующий ProcessMessage.

Тут ещё хорошо подходит шаблон конечного автомата.

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

неправильно. это не должен быть цикл в понимании for, repeat, while

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

TForm1=class(TForm)
  ...
  ProcessStarted:boolean;
  PressCount:integer;
  ...
end;

procedure TForm1.Button1Click(...)
begin
  StartProcess();
end;

procedure TForm1.Button2Click()
begin
  CheckProcessEnd();
end;

procedure TForm1.StartProcess();
begin
  ProcessStarted:=true;
  PressCount:=0;
  button1.enabled := false;
  button2.enabled := true;
end;

procedure TForm1.CheckProcessEnd;
const PRESS_COUNT_PENDING=5;
begin
  inc(PressCount);
  if (PressCount=PRESS_COUNT_PENDING) then
  begin
    ProcessStarted:=false;
    button1.enabled:=true;
    button2.enabled:=false;
  end;
end;

да. именно конечный автомат это и есть.

Изменено пользователем krapotkin
Ссылка на комментарий
  • 0
1 час назад, Steepe_Hare сказал:

Задача: дождаться действий пользователя (допустим, 5 раз нажать на Button2) и только потом выполнять следующий после этого код

А что мешает так изменить ваш пример
 

procedure TForm1.Button1Click(Sender: TObject);
begin
  i := 0;
  Finish := False;
  Memo1.Lines.Add('Start');
  Button2.Enabled := True;

  Button1.Enabled := False;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Inc(i);
  Memo1.Lines.Add(IntToStr(i));

  if (i = 5) then
  begin
    Finish := True;
    Button2.Enabled := False;
    Ogogo();
  end;
end;

procedure TForm1.Ogogo();
BEGIN
  //while not Finish do
    //Application.ProcessMessages;
  Memo1.Lines.Add('Finish');
  Button1.Enabled := True;
END;

 

Изменено пользователем GASCHE
Ссылка на комментарий
  • 0
33 минуты назад, GASCHE сказал:

А что мешает так изменить ваш пример
 


procedure TForm1.Button1Click(Sender: TObject);
begin
  i := 0;
  Finish := False;
  Memo1.Lines.Add('Start');
  Button2.Enabled := True;

  Button1.Enabled := False;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Inc(i);
  Memo1.Lines.Add(IntToStr(i));

  if (i = 5) then
  begin
    Finish := True;
    Button2.Enabled := False;
    Ogogo();
  end;
end;

procedure TForm1.Ogogo();
BEGIN
  //while not Finish do
    //Application.ProcessMessages;
  Memo1.Lines.Add('Finish');
  Button1.Enabled := True;
END;

 

нужно отработать код, а затем вернуться в начало цикла

Ссылка на комментарий
  • 0
13 минут назад, GASCHE сказал:

Так где это в вашем примере?

Нет этого.

Но просто хотел узнать заменитель Application.ProcessMessages для Android. Если это так плохо и неверно, то зачем оно в FMX?

Ссылка на комментарий
  • 0
14 минут назад, Steepe_Hare сказал:

Если это так плохо и неверно, то зачем оно в FMX?

Так использовать такую конструкцию 

while not Finish do
   Application.ProcessMessages;

и для Windows плохо :(  

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

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

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

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

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

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

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

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

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

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

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