Delphi:如何防止单个线程应用丢失响应?

我正在使用Delphi开发一个单线程应用程序,这将执行一个耗时的任务,如下所示:
// time-consuming loop
For I := 0 to 1024 * 65536 do
Begin
    DoTask();
End;

循环启动时,应用程序将丢失对最终用户的响应.那不是很好.由于其复杂性,我也不想将其转换为多线程应用程序,因此我相应地添加了Application.ProcessMessages,

// time-consuming loop
For I := 0 to 1024 * 65536 do
Begin
DoTask();
Application.ProcessMessages;
End;

但是,这次虽然应用程序将响应用户操作,但循环中消耗的时间远远超过原始循环,大约10倍.

有没有一个解决方案来确保应用程序不会丢失响应,同时不会过多地增加消耗的时间?

解决方法

你说 :

I also do not want to convert it into a multi-thread application
because of its complexity

我可以认为这意味着两件事之一:

>您的应用程序是一堆庞大的遗留代码,如此庞大且编写​​得如此糟糕,以至于将DoTask封装在一个线程中意味着需要进行大量的重构,而这些重构无法实现可行的业务案例.
>您认为编写多线程代码太“复杂”而且您不想学习如何执行此操作.

如果案例是#2则没有任何借口 – 多线程是这个问题的明确答案.将一个方法推入一个线程并不是那么可怕,你将成为一个更好的开发人员来学习如何做到这一点.

如果病例是#1,我把这个留给你来决定,然后在医生给你一个4岁的孩子第一次尝试吗啡时犹豫不决,我会注意到在这个循环期间你会用这个来调用Application.ProcessMessages 6700万次:

For I := 0 to 1024 * 65536 do
Begin
  DoTask();
  Application.ProcessMessages;
End;

这种犯罪被掩盖的典型方式就是每次运行循环时都不调用Application.ProcessMessages.

For I := 0 to 1024 * 65536 do
Begin
  DoTask();
  if I mod 1024 = 0 then Application.ProcessMessages;
End;

但是如果Application.ProcessMessages实际上比DoTask()执行的时间长十倍,那么我真的会质疑DoTask的复杂程度,以及将它重构为一个线程是否真的是一项艰巨的任务.使用上面的代码修复此问题将导致每个遵循并运行该代码的开发人员永远诅咒您的名字.这真的是可怕的,可怕的做法,除了最极端的情况外,应该尽量避免.被警告.如果您使用ProcessMessages解决这个问题,那么您真的应该将其视为一个临时解决方案,并且如果时间压力暂时不允许,请尽一切努力在更方便的时间重构它.

特别要注意的是,使用ProcessMessages意味着你必须确保所有的消息处理程序都是可重入的,否则你将会被你将要理解的神秘错误所困扰.

相关文章

 从网上看到《Delphi API HOOK完全说明》这篇文章,基本上都...
  从网上看到《Delphi API HOOK完全说明》这篇文章,基本上...
ffmpeg 是一套强大的开源的多媒体库 一般都是用 c/c+&#x...
32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和ED...
1 mov dst, src dst是目的操作数,src是源操作数,指令实现的...