1. Запуск цикла сообщений одновременно с запуском вашего скрипта
Я хочу, чтобы мой двигатель работал так же быстро, как
возможно пока
события Windows, так что другие
приложения все еще реагируют, когда
тугая петля, похожая на вышесказанное
встречаются.
Лучший способ продолжить выполнение цикла сообщений при выполнении другой операции - переместить эту другую операцию в другой поток. Другими словами, переместите интерпретатор сценариев во второй поток и свяжитесь с ним из основного потока пользовательского интерфейса, который выполняет цикл обработки сообщений.
Когда вы говорите Borland C ++, я предполагаю, что вы используете C ++ Builder? В этой ситуации основной поток является единственным, который взаимодействует с пользовательским интерфейсом, и его цикл сообщений запускается через Application->Run
. Если вы периодически вызываете Application->ProcessMessages
в своих обратных вызовах библиотеки, это может привести к повторным вызовам. Не делай этого.
В одном комментарии к вашему вопросу предлагалось перенести каждый экземпляр скрипта в отдельную ветку. Это было бы идеально. Однако остерегайтесь проблем с библиотеками DLL, которые скрипты вызывают, если они сохраняют состояние - библиотеки DLL загружаются для каждого процесса, а не для каждого потока, поэтому, если они сохраняют состояние, вы можете столкнуться с проблемами потоков. На данный момент, чтобы просто ответить на ваш текущий вопрос, я бы предложил перенести все ваши скрипты в другой поток.
Вы можете общаться между потоками разными способами, например, отправляя сообщения между ними, используя PostMessage или PostThreadMessage . Поскольку вы используете Borland C ++, у вас должен быть доступ к VCL. У него есть хороший класс-оболочка для потоков, называемый TThread . Получите от этого и поместите ваш цикл сценария в Execute. Вы можете использовать Синхронизировать (блокирует ожидание) или Очередь (не блокировать; метод может быть запущен в любое время, когда целевой поток обрабатывает свой цикл сообщений) для запуска методов в контекст другого потока.
В качестве примечания:
так что другие
приложения все еще реагируют, когда
тугая петля, похожая на вышесказанное
встречаются.
Это странно. В современной многозадачной версии Windows другие приложения должны реагировать, даже если ваша программа очень занята. Вы делаете что-то странное с приоритетами потоков или используете много памяти, чтобы другие приложения были выгружены?
2. Обработка бесконечного цикла в скрипте
Вы пишете:
ничто не мешает кому-то
написание сценария, который просто делает
тугая петля вот так:
, в то время как (1) х = 1; ENDWHILE
Что означает, что мой основной цикл никогда не будет
войти в состояние сна и так процессор
идет до 100% и запирает
система.
но фраза как это сделать:
Также было бы неплохо иметь возможность
установить максимальное использование процессора моим двигателем
можно использовать и уменьшить процессор
использование путем вызова случайного
Sleep (1) ..
Итак, мой второй вопрос: как я могу
затем уменьшить использование процессора до
необходимый уровень?
Я думаю, вы выбрали неправильный подход. Бесконечный цикл, такой как while(1) x=1; endwhile
, является ошибкой в скрипте, но он не должен уничтожать ваше хост-приложение. Простое регулирование процессора не сделает ваше приложение способным справиться с ситуацией. (И использование большого количества CPU не обязательно является проблемой: если работа доступна для запуска CPU, сделайте это! Нет ничего святого в том, чтобы использовать только небольшую часть CPU вашего компьютера . использовать в конце концов.) Что (я думаю) вы действительно хотите, чтобы ваше приложение могло продолжать отвечать при запуске этого сценария (решается вторым потоком), а затем:
Определите, когда скрипт «не отвечает» или не вызывает ваши обратные вызовы
Уметь действовать, например, спрашивать пользователя, хочет ли он прекратить выполнение сценария
Примером другой программы, которая делает это, является Firefox.Если вы перейдете на страницу с некорректно работающим сценарием, в конечном итоге вы получите диалоговое окно с вопросом, хотите ли вы остановить выполнение сценария.
Не зная больше о том, как на самом деле интерпретируется или выполняется ваш сценарий, я могу:дать подробный ответ на эти два вопроса.Но я могу предложить подход, который:
Ваш интерпретатор, вероятно, запускает цикл, получает следующую инструкцию и выполняет ее.Ваша интерактивность в настоящее время обеспечивается обратным вызовом, запущенным из одной из выполняемых инструкций.Я бы посоветовал воспользоваться этим, чтобы ваш обратный вызов просто записывал время последнего вызова.Затем в вашем потоке обработки каждая инструкция (или каждые десять или сто) сверяет текущее время с временем последнего обратного вызова.Если прошло много времени, скажем пятнадцать или тридцать секунд, это может указывать на то, что скрипт застрял.Уведомить главный поток, но продолжить обработку.
Для "времени", вероятно, достаточно что-то вроде GetTickCount .
Следующий шаг: Ваш основной пользовательский интерфейсПоток может реагировать на это, спрашивая пользователя, что делать.Если они хотят завершить сценарий, свяжитесь с потоком сценария, чтобы установить флаг.В цикле обработки вашего скрипта снова каждая инструкция (или сотня) проверяет этот флаг, и, если он установлен, останавливается.
Когда вы переходите к наличию одного потока на интерпретатор скрипта, вы TThread
Terminated
флаг для этого.Идиоматически для чего-то, что работает бесконечно в потоке, вы запускаете цикл while (!Terminated && [any other conditions])
в вашей функции Execute
.
Чтобы на самом деле ответить на ваш вопрос об использовании меньшего количества процессоров, лучший подходвозможно изменить приоритет вашего потока, используя SetThreadPriority на более низкий приоритет, такой как THREAD_PRIORITY_BELOW_NORMAL
.Он все равно будет работать, если больше ничего не нужно для запуска.Это повлияет на производительность вашего скрипта.Другой подход заключается в использовании Sleep , как вы предлагаете, но это действительно искусственно.Возможно, SwitchToThread немного лучше - он уступает другому потоку, который выбирает ОС.Лично я думаю, что процессор предназначен для использования, и если вы решите проблему интерактивного интерфейса пользователя и обработки неконтролируемых сценариев, тогда не должно быть проблем с использованием всего процессора, если он нужен вашему сценарию.Если вы используете «слишком много» CPU, возможно, сам интерпретатор может быть оптимизирован.Вам нужно будет запустить профилировщик и выяснить, на что тратится время процессора.