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

Помогите разобраться с потоком


walexw

Вопрос

rad studio 10 seattle, приложение под андроид
Споткнулся на простой задаче. Нужно, чтобы во время обработки данных (несколько запросов SQL) на экране крутился AniIndicator.
Создал класс domThread на базе потока, в нем одна процедура (код на С++)

void __fastcall domThread::Execute()
{
  frm->aniIndic->Enabled = true; // Запуск индикатора
  frm->aniIndic->Visible = true;
}


В основном коде пишу: (при клике на кнопку)

domThread *aiThread = new domThread(false); // Сразу запустить поток с крутящимся индикатором
Sleep(5000);                                // Это задержка 5 сек. пока заменяет выполнение запросов



По факту получаю следующее, при нажатии кнопки сначала 5 секунд пауза, затем включается индикатор.
Что я делаю неправильно? Разъясните, я впервые с потоками столкнулся.
 

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

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

  • 0
  • Администраторы

Все просто.

  1. Отрисовка индикатора идёт в главном потоке. Вызывая Sleep в главном потоке, вы лочите главный поток на 5 секунд и как следствие всю отрисовку (Даже если вы выставите раньше Enabled=True). 
  2. С UI компонентами можно работать только в главном потоке, поэтому все вызовы, работающие с компонентами из других потоков нужно завернуть в TThread.Synchronize.
Ссылка на комментарий
  • 0
  • Модераторы
14 минут назад, walexw сказал:

rad studio 10 seattle, приложение под андроид
Споткнулся на простой задаче. Нужно, чтобы во время обработки данных (несколько запросов SQL) на экране крутился AniIndicator.
Создал класс domThread на базе потока, в нем одна процедура (код на С++)
void __fastcall domThread::Execute()
{
  frm->aniIndic->Enabled = true; // Запуск индикатора
  frm->aniIndic->Visible = true;
}
В основном коде пишу: (при клике на кнопку)
domThread *aiThread = new domThread(false); // Сразу запустить поток с крутящимся индикатором
Sleep(5000);                                                        // Это задержка 5 сек. пока заменяет выполнение запросов

По факту получаю следующее, при нажатии кнопки сначала 5 секунд пауза, затем включается индикатор.
Что я делаю неправильно? Разъясните, я впервые с потоками столкнулся.
 

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

1) использовать компоненты Ярослава

2) анимацию запускаем до потока (в котором выполняются разного рода запросы), по завершению операции в !синхронизации! выключаем анимацию

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

Сделал все, как здесь посоветовали.
В основном потоке делаю видимым индикатор и включаю его, затем запускаю отдельный поток в который перенес все запросы к БД.
В конце из отдельного потока выключаю индикатор и делаю его невидимым.
Сначала все получилось замечательно, как мне нужно было.
Но со временем заметил, что на устройстве (смартфон, андроид 6) индикатор останавливается, но не исчезает.
Застывший полукруг посреди экрана. Это бывает не всегда. Периодичность не замечена.
Что может быть? Сам функционал остается работать, но вот этот полукруг...
Посоветуйте, как подправить!

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

Сделал все, как здесь посоветовали.
В основном потоке делаю видимым индикатор и включаю его, затем запускаю отдельный поток в который перенес все запросы к БД.
В конце из отдельного потока выключаю индикатор и делаю его невидимым.
Сначала все получилось замечательно, как мне нужно было.
Но со временем заметил, что на устройстве (смартфон, андроид 6) индикатор останавливается, но не исчезает.
Застывший полукруг посреди экрана. Это бывает не всегда. Периодичность не замечена.
Что может быть? Сам функционал остается работать, но вот этот полукруг...
Посоветуйте, как подправить!

1) надеюсь вы его динамически не создаете? с этим компонентом есть проблемы с динамическим созданием.

2) показывайте код

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

aIndic - индикатор, лежит на форме, при загрузке приложения ставлю его в середину и делаю Visible=false;

Запускаю индикатор по нажатию кнопки:
aIndic->Enabled  = true;
aIndic->Visible     = true;
Теперь запускаю поток, в котором несколько запросов к БД и их обработка
domThread  *aiThread = new domThread(false);
Больше по кнопке никакого кода нет.

Теперь поток: (FreeOnTerminate = true;)
void __fastcall domThread::Execute()
{
тут те самые запросы и их обработка, в конце:
frm->aIndic->Visible  = false;
frm->aIndic->Enabled  = false;
Terminate();
}

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

aIndic - индикатор, лежит на форме, при загрузке приложения ставлю его в середину и делаю Visible=false;

Запускаю индикатор по нажатию кнопки:
aIndic->Enabled  = true;
aIndic->Visible     = true;
Теперь запускаю поток, в котором несколько запросов к БД и их обработка
domThread  *aiThread = new domThread(false);
Больше по кнопке никакого кода нет.

Теперь поток: (FreeOnTerminate = true;)
void __fastcall domThread::Execute()
{
тут те самые запросы и их обработка, в конце:
frm->aIndic->Visible  = false;
frm->aIndic->Enabled  = false;
Terminate();
}

а где синхронизация?

вы выполняете работу с визуальными компонентами без синхронизации

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

а где синхронизация?

вы выполняете работу с визуальными компонентами без синхронизации

void __fastcall domThread::UpdateAnimation()
{
//        Действительно мой код без синхронизации.
//        Я просто не знаю какую команду надо ставить в синхронизацию для TAniIndikator
//        Подскажите.
}

Ссылка на комментарий
  • 0
  • Модераторы
void __fastcall domThread::UpdateAnimation()
{
frm->aIndic->Visible  = false;
frm->aIndic->Enabled  = false;
}

незнаю как на си будет, но примерно так

void __fastcall domThread::Execute()
{
Synchronize( UpdateAnimation );
Terminate();
} 
Изменено пользователем ZuBy
Ссылка на комментарий
  • 0
  • Модераторы
3 часа назад, walexw сказал:

void __fastcall domThread::UpdateAnimation()
{
//        Действительно мой код без синхронизации.
//        Я просто не знаю какую команду надо ставить в синхронизацию для TAniIndikator
//        Подскажите.
}

Вот посмотрите справку System.Classes.TThread.Synchronize

Примеры на С++: ThreadSynchronize (C++) и TThreadYield (C++)

Ссылка на комментарий
  • 0
В ‎29‎.‎09‎.‎2016 в 13:29, ZuBy сказал:

void __fastcall domThread::UpdateAnimation()
{
frm->aIndic->Visible  = false;
frm->aIndic->Enabled  = false;
}

незнаю как на си будет, но примерно так


void __fastcall domThread::Execute()
{
Synchronize( UpdateAnimation );
Terminate();
} 

ZuBy, спасибо, все так и сделал, получилось то что надо!

Ссылка на комментарий
  • 0
В 30.09.2016 в 19:50, walexw сказал:

Terminate();

это как гомеопатия

хуже не будет, но и смысла нет )

и в результате получили что весь код потока исполняется в главном потоке
т.е. и организация потока бессмысленна

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

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

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

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

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

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

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

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

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

×
×
  • Создать...