У меня есть приложение с графическим интерфейсом, которое я создаю с помощью wxWidgets. Как часть функциональности, я должен запускать «задачи» одновременно с манипулированием окном GUI. Например, я могу запустить код:
long currentTime = wxGetLocalTime();
long stopTime = wxGetLocalTime() + 3;
while (wxGetLocalTime() != stopTime) {}
wxMessageBox("DONE IN APP");
В течение этих 3 секунд мое приложение будет по существу заморожено, пока не отобразится wxMessageBox. Есть ли способ сделать этот запуск в фоновом режиме без использования нескольких потоков? Это создает проблемы для приложения, которое я разрабатываю.
Мне было интересно, если есть какие-то типы обработки событий, которые могут быть использованы. Любая помощь очень ценится.
Попробуй это:
long currentTime = wxGetLocalTime();
long stopTime = wxGetLocalTime() + 3;
while (wxGetLocalTime() != stopTime) {
wxYield();
}
wxMessageBox("DONE IN APP");
Существует 3 способа выполнения трудоемких задач в приложениях GUI wx:
Безусловно, наиболее предпочтительным является использование другого потока. Объяснение того, что приложение «очень интенсивно работает с графическим интерфейсом», на самом деле не имеет никакого смысла для меня, я думаю, вам следует серьезно пересмотреть дизайн своей программы, если его интенсивность графического интерфейса (независимо от того, что это такое) не позволяет вам использовать фоновые рабочие потоки. Если вы используете этот подход, он довольно прост, но обратите особое внимание на проблемы завершения потока / программы. В частности, вам нужно будет либо дождаться завершения потока (приемлемо, если запуск не займет много времени), либо явно отменить его перед выходом из программы.
использование EVT_IDLE
событие для выполнения вашей задачи, когда нет других событий для обработки. Это не так уж плохо для небольших задач, которые можно разбить на достаточно маленькие части, так как вы должны иметь возможность возобновить обработку в вашем обработчике. Не забудьте позвонить event.RequestMore()
продолжать получать праздные события, даже если ничего не происходит иначе.
Худшее и самое опасное было позвонить wxYield()
как предполагает другой ответ. Это может показаться простым на первый взгляд, но вы будут жалею, что сделал это позже, потому что это может создать чрезвычайно трудные для устранения проблемы повторного входа в ваш код. Если вы используете его, вам нужно остерегаться повторного входа везде, и вы должны действительно понимать, что именно делает эта функция.
Я знаю, что это поздно для игры, но …
Я успешно использовал метод EVT_IDLE для YEARS (еще в 90-х годах с Motif изначально). Основная идея состоит в том, чтобы разбить вашу задачу на маленькие части, где каждая часть вызывает следующую часть (например, связанный список). Механизм для этого заключается в использовании метода CallAfter () (конечно, с использованием C ++). Вы просто «CallAfter ()» как последний шаг в части, и это позволит основному циклу GUI выполнить другую итерацию и, возможно, обновить элементы GUI и тому подобное, прежде чем вызывать следующую часть. Просто помните, чтобы кусочки были маленькими.
Использование фонового потока действительно приятно, но может оказаться сложнее, чем вы думаете … в конце концов. Пока вы знаете, что данные, с которыми вы работаете в фоновом режиме, больше не будут затронуты / просмотрены, все в порядке. Если вы знаете, что это так, то это путь. Этот метод позволяет GUI оставаться полностью отзывчивым во время фоновых вычислений (изменение размера / перемещение окна и т. Д.)
В любом случае, просто не забудьте десенсибилизировать соответствующие элементы графического интерфейса в качестве первого шага, чтобы не было случайного запуска одной и той же фоновой задачи несколько раз (например, случайное нажатие кнопки несколько раз подряд, которая запускает фоновый поток). ,