Member 10250894 Ответов: 3

Попытка создать последовательные задачи в пользовательском интерфейсе с интервальным таймером


У меня есть приложение, использующее Rad Studio c++ 10.2.
Моя проблема состоит в том, чтобы иметь последовательность :SetupDelay ->ExerciseDelay->задержка отдыха
прежде чем перейти к следующему упражнению.
Пользовательский интерфейс представляет текущие атрибуты упражнения и должен последовательно ждать каждой из этих задержек, прежде чем перейти к следующей.
У меня есть следующий код, использующий TTimer, который работает на Windows, но когда я компилирую для Android, он вызывает сбой пользовательского интерфейса.

Я ищу портативный метод,который поддерживает все платформы (Win,OSX,IOS, Android), поддерживаемые Rad Studio. Ниже приведен код, который я впервые использовал для windows:


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


Мой процесс таков: (последовательный процесс в пользовательском интерфейсе)

1: отображение текущих атрибутов упражнений

2: задержка для установки - таймер обратного отсчета обновляет метку каждую секунду

3: задержка для тренировки времени - таймер обратного отсчета обновляет метку каждую секунду

4: задержка для времени отдыха - таймер обратного отсчета обновляет метку каждую секунду

5; обновляйте счетчик набора и цикл (3-4) до тех пор, пока все наборы для текущего упражнения не будут завершены

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

Чтобы уточнить: код, написанный для Rad Studio, является мульти-устройством, поэтому один и тот же код, скомпилированный/запущенный для Windows, терпит неудачу на Android. Сбой на Android выглядит следующим образом:
При первом запуске таймера приложение для Android зависает, и ни один из таймеров не запускается. Если я нажму любую из кнопок, приложение выйдет из строя. Если я ничего не делаю, приложение просто сидит и ничего не делает.

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

Любая помощь или идея будут оценены по достоинству.

Что я уже пробовал:

Ниже приведен мой существующий код, работающий для Windows.


Я попытался использовать отдельный поток для задержки, но проблема все еще заключается в том, что пользовательский интерфейс, ожидающий завершения задержки, постоянно проверяет состояние задержки, что эффективно останавливает пользовательский интерфейс. Насколько я могу определить, Android не поддерживает ProcessMessages, поэтому любое решение не должно использовать этот метод.

void __fastcall	TTabbedwithNavigationForm::DoDelay( int delay )
{
int	pdl;
char	buf[ 256 ];

    NEXT = false;
    CANCEL = false;

    DelayCounter = delay;
    Timer1 ->Enabled = true;

// we use this loop so that ProcessMessages and Label updates are not called too often. Without this there is a noticeable lag in response.
    pdl = 5000;

    while ( DelayCounter > 0 )
    {
	if ( --pdl == 0 )
	{
	    sprintf( buf, "%3d", DelayCounter );
	    LBL_RestExerciseTime ->Text = buf;

	    Application ->ProcessMessages();

	    pdl = 5000;
	}
	else
	{
	}

	if ( CANCEL == true )
	    break;

	if ( NEXT == true )
	    break;
    }

    Timer1 ->Enabled = false;
}
//---------------------------------------------------------------------------
void __fastcall TTabbedwithNavigationForm::Timer1Timer(TObject *Sender)
{
    if ( DelayCounter > 0 )
    {
	--DelayCounter;

	if ( STOP == true || CANCEL == true )
	{
	    Timer1 ->Enabled = false;
	    DelayCounter = 0;
	}

	if ( DelayCounter == 0 )
	{
	    Timer1 ->Enabled = false;
	}
    }
}

Richard MacCutchan

Вы должны показать нам код Android и объяснить, где именно происходит сбой.

Rick York

У меня нет прямого решения вашей проблемы, но на вашем месте я бы реализовал для этого государственную машину. Это не обязательно должно быть общей целью, если вы хотите быть быстрым. Причина в том, что вы можете легко переходить между состояниями, у вас не будет кучки флагов повсюду, и вы можете поддерживать таймер обновления. Состояние будет определять, когда кнопки включены и отключены. Часто для такого рода вещей достаточно нескольких флагов, но когда вы бросаете достаточно кривых шаров, их нужно взять немного дальше, и я думаю, что SM будет правильным способом для вас.

3 Ответов

Рейтинг:
23

Gerry Schmitz

Почему у вас есть "задержки", когда вы используете "таймеры"?

Если ваша частота обновления составляет один раз в секунду, то ваш "интервал" s/b составляет 1 секунду.

Вы можете поместить все свои "задачи" в очередь и выскакивать по одной в конце каждого x интервала (например).

Пользовательский интерфейс остается отзывчивым, пока таймер ждет запуска (и вы не "задерживаетесь").

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


Member 10250894

My timer has a 1 sec resolution but since the user can ask for any length it is required that I wait until that requested delay. If I start the timer and wait even 1 second for it to timeout the entire sequence would have completed. The "Delay" here is the time the user needs to do an exercise period, a rest period or to prepare for another exercise. Maybe delay is a bad moniker for that. The issue for me is to actually wait for each of these phases of an exercise cycle while still being able to display the countdown time and the elapsed time and still being responsive to button clicks. Dang Android !!! I wonder what surprises I will encounter when I try to run this on IoS???

Рейтинг:
2

Stefan_Lang

I tried using a separate thread for the delay, but the issue is still the UI waiting for the delay to finish involves constantly checking the delay status which effectively halts the UI.
Нет, именно в этом и заключается проблема: вы не можете постоянно проверять свою собственную функцию, вместо этого вам нужно переместить эту проверку в очередь событий - тогда вам даже не нужно заботиться о создании отдельного потока! Видеть Операции с событиями таймера - приложения Windows | Microsoft Docs[^]

В принципе, когда таймер (задержка) запускается, вы говорите таймеру отправить событие через n секунд, а затем вам нужно предоставить функцию обработчика событий, которая вызывается при срабатывании события.

Я не смогу быть более конкретным - прошли десятилетия с тех пор, как я в последний раз программировал пользовательский интерфейс, и я понимаю, что с тех пор все изменилось. Но таймеры все еще существуют, как и события.


Рейтинг:
0

Member 10250894

После перепробования всех перестановок последовательных задержек и потоков (и ProcessMessages ) Я пришел к выводу, что государственная машина была действительно правильным решением здесь.

В итоге я использовал 2 таймера, 1 для управления машиной состояний и второй таймер, используемый машиной состояний для определения времени фактических задержек, необходимых в последовательностях упражнений.

Код успешно работает как на windows, так и на android. У меня еще нет идентификатора разработчика apple (я понимаю, что вы должны платить за боковую загрузку приложений на устройстве apple.) но я не вижу причин, по которым это решение не будет работать и там.

Я ценю все ответы.