Есть пара очевидных проблем с вашим кодом.
Во-первых, вы тратите много циклов ЦП, вычисляя одни и те же значения снова и снова. Значения AA..ZZ не изменятся, поэтому нет необходимости строить их снова и снова. Попробуйте что-то вроде этого: создайте третий TStringList. Пройдите и заполните его всеми возможными перестановками AA..ZZ с вашей двойной петлей. После того, как все закончится, выполните цикл и объедините этот список предварительно вычисленных строк со значениями в slist1
. Вы должны увидеть довольно большой импульс от этого.
(Или, если время абсолютно неоправданно, напишите небольшую небольшую программу, которая вычислит список перестановок и сохранит его в текстовый файл, а затем скомпилирует его в свое приложение как строковый ресурс, который можно загрузить во время выполнения.)
Во-вторых, и это, вероятно, то, что вас убивает, вы не должны иметь ProcessMessages и вызовов Sleep в самом внутреннем цикле. Sleep(1);
звучит так, как будто это означает «спать в течение 1 миллисекунды», но Windows не обеспечивает такую точность. То, что вы в конечном итоге получаете, это «спать по крайней мере 1 милисекунда». Он освобождает процессор до тех пор, пока Windows не вернется к нему, что обычно составляет порядка 16 миллисекунд. Таким образом, вы добавляете задержку в 16 мс (плюс столько, сколько занимает ProcessMessages) в очень узкий цикл, который, вероятно, займет всего несколько микросекунд для выполнения оставшейся части кода.
Если вам нужно что-то подобное для поддержания отзывчивости интерфейса, оно должно быть во внешнем цикле, а не во внутреннем, и вам, вероятно, даже не нужно запускать его каждую итерацию. Попробуйте что-то вроде if ch mod 100 = 0 then //sleep and process messages here
. Предложение Крейга перенести эту задачу в рабочий поток также поможет, но только в том случае, если вы знаете достаточно о потоках, чтобы сделать это правильно. Они могут быть хитрыми.