Використання методу sleep () - stack overflow російською

Ласкаво просимо в захоплюючий світ UI-програмування! Вам доведеться трохи перевчитися: тут все не так, як в програмах командного рядка. Тут все фонові завдання, пов'язані з інтерфейсом, відбуваються не негайно, як тільки ви скомандували, а впереміш з вашою роботою. Все це відбувається в фіксованому потоці, так званому UI-потоці.

Що відбувається у вашому коді?

  1. Ви блокуєте UI-потік на півсекунди, потім встановлюєте текст кнопки. Встановлюється внутрішній прапор в графічній бібліотеці, який говорить «коли буде вільна хвилинка, треба оновити button».
  2. Ви негайно знову блокуєте UI-потік на півсекунди, і перевстановлюєте текст кнопки. Оскільки «вільна хвилинка» (вона ж «idle loop») так і не наступила, текст оновитися не встиг. Крім того, на час блокування нікому обробляти події від миші і клавіатури (бо UI-потік зайнятий sleep 'ом), так що програма виглядає зависла.
  3. Потім ви знову встановлюєте текст кнопки, це нічого не змінює, так як прапор, який вказує на необхідності оновлення, вже зведений.
  4. І так далі, 11 раз.
  5. В кінці-кінців, коли ваш цикл закінчився, UI-потік нарешті звільнився, і може отрисовать ваші зміни. Ви нарешті бачите 0.

У чому суть проблеми? Ви не повинні робити довгі операції в UI-потоці. Thread.sleep - одна з таких операцій, але багато ще і читають файли, вантажать дані з мережі або звертаються до бази даних. Ви маєте право завантажувати UI-потік роботою лише на кілька мілісекунд. На весь час довгої операції, що біжить в UI-потоці, додаток буде виглядати завислим, і обробники UI-подій викликатися не будуть. Така поведінка програми відразу перетворює її в студентську саморобку.

Оновлення UI, реакція на мишу, перерисовка контролів - все відбувається в UI-потоці, в той момент, коли цей потік нічим не зайнятий. Хороша програма з UI повинна бути подієво-орієнтованої, а не імперативної: ви повинні не самі рулити ходом програми, а лише реагувати на події короткими за часом обработчиками.

Що потрібно робити? Є два шляхи. Простий шлях, який цілком підходить для ваших цілей: чи не блокуєте UI-потік, а використовуєте таймер, який йде з вашої UI-бібліотекою. Він викличе ваш обробник в потрібний час, ви встановите там текст кнопки, і закінчите обробку. тим самим ви відпустіть UI-потік, щоб він зміг оновити UI.

Складний шлях, який застосовується, якщо вам дійсно потрібно виконати тривалу операцію. В цьому випадку ви створюєте окремий потік (thread), в якому і виконуєте потрібну операцію. Результати роботи ви в потрібний момент посилаєте в UI-потік, який повинен просто оновити UI. Зауважте, що в цьому випадку програмування стає набагато складніше, тому що вам доведеться піклуватися про синхронізацію, блокування і комунікації між потоками (просто глобальна змінна не котить). Але для вашого випадку це зайве, цілком вистачить простого таймера.

Схожі статті