有没有更快的方法?我基本上需要一次将 AA-ZZ 添加到数千条记录中。
仅列出 35 项就需要相当长的时间才能完成,更不用说列出 1000 项了。
procedure Tmainform.btnSeederClick(Sender: TObject);
var
ch,ch2:char;
i:integer;
slist1, slist2:TStrings;
begin
slist1:= TStringList.Create;
slist2:= TStringList.Create;
slist1.Text :=queuebox.Items.Text;
for ch := 'a' to 'z' do
begin
for ch2 := 'a' to 'z' do
begin
//<p></p>
for I := 0 to slist1.Count - 1 do
begin
application.ProcessMessages; // so it doesn't freeze the application in long loops. Not 100% sure where this should be placed, if at all.
sleep(1); //Without this it doesn't process the cancel button.
if cancel then Break;
slist2.Add(slist1.Strings[i]+ch+ch2);
end;
end;
end;
insertsingle(slist2,queuebox);
freeandnil(slist1);
freeandnil(slist2);
结束;
感谢您的帮助
最佳答案
您的代码存在一些明显的问题。
首先,您会浪费大量 CPU 周期来一遍又一遍地计算相同的值。 AA..ZZ 值不会改变,因此无需一遍又一遍地构建它们。尝试这样的操作:创建第三个 TStringList。用双循环遍历并用所有可能的 AA..ZZ 排列填充它。完成后,循环遍历此预先计算的字符串列表并将其与 slist1
中的值合并。您应该会看到一个相当大的提升。
(或者,如果时间绝对宝贵,请编写一个小程序来计算排列列表并将其保存到文本文件中,然后将其作为可以在运行时加载的字符串资源编译到您的应用程序中。)
其次,这可能就是要你命的原因,你不应该在最里面的循环中使用 ProcessMessages 和 Sleep 调用。 Sleep(1);
听起来像是“ sleep 1 毫秒”,但 Windows 不提供这种精度。您最终得到的是“ sleep 至少 1 毫秒”。它会释放 CPU,直到 Windows 恢复使用它,这通常大约为 16 毫秒。因此,您要在一个非常紧密的循环中添加 16 毫秒的延迟(加上 ProcessMessages 所需的时间),该循环可能只需要几微秒即可执行其余代码。
如果您需要类似的东西来保持 UI 响应,它应该位于最外层循环中,而不是内部循环中,并且您甚至可能不需要每次迭代都运行它。尝试类似 if ch mod 100 = 0 then//sleep and process messages here
。克雷格建议将此任务移至工作线程也会有所帮助,但前提是您对线程有足够的了解才能正确完成它。它们可能很棘手。
关于Delphi循环速度问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2098966/