Windows 在桌面上用鼠标指针变慢

Windows slowing down with mouse pointer on destop

我有一个奇怪的问题。我开始了大约。 160道工序。现在,如果鼠标指针在桌面上,一些过去需要 100 毫秒的操作现在需要 10 秒,尽管系统的总负载为 13-16%。甚至像 processhacker 这样的第三方程序也会变慢并且不会刷新他们的图形用户界面。如果我将鼠标指针移到某个 window 上,无论是哪个(可能是记事本),甚至任务栏都可以帮助一切恢复正常。 Processhacker 正在刷新他的列表,响应速度恢复到 100 毫秒。 由于 Microsoft-Support 不会帮助使用 - 因为或进程是在 Borland-Delphi 中编程的,我们不知道如何找出这里发生的事情。 一位同事试图用这个小测试程序重现效果:

unit Unit1;

interface

uses
  Forms,
  ExtCtrls,
  Classes,
  Controls,
  StdCtrls;

const
  DEFAULT_INTERVAL = 31;
  MOD_VALUE = 5;
  MOD_INTERVAL = DEFAULT_INTERVAL * MOD_VALUE;
  DEVIATION_BLACK = 2;
  DEVIATION_RED = 10;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    Timer: TTimer;
    lastTime: TDateTime;
    procedure OnTimer(Sender: TObject);
    procedure SetLabel(lbl: TLabel);
  end;

var
  Form1: TForm1;
  GCounterT: Integer;

implementation

uses
  Windows,
  Graphics,
  SysUtils,
  DateUtils;

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  Self.DoubleBuffered := True;

  Timer := TTimer.Create(nil);
  Timer.Interval := DEFAULT_INTERVAL;
  Timer.OnTimer := OnTimer;

  GCounterT := 0;
  lastTime := Now();
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Timer.Free;
end;

procedure TForm1.OnTimer(Sender: TObject);
begin
  Inc(GCounterT);
  if (GCounterT mod MOD_VALUE) = 0 then begin
    SetLabel(Label1);
    GCounterT := 0;
  end;
end;

procedure TForm1.SetLabel(lbl: TLabel);
var
  newValue: string;
  nowTime: TDateTime;
  msDiff: Integer;
  newColor: TColor;
begin
  if IsIconic(Application.Handle) then Exit;

  nowTime := Now();
  msDiff := MilliSecondsBetween(nowTime, lastTime);
  lastTime := nowTime;

  newValue := Format('TTimer:      %s  dev: %d',[FormatDateTime('ss.zzz', nowTime), msDiff - MOD_INTERVAL]);
  if   (msDiff <= (MOD_INTERVAL + DEVIATION_BLACK))
   and (msDiff >= (MOD_INTERVAL - DEVIATION_BLACK)) then
    newColor := clGreen
  else if (msDiff <= (MOD_INTERVAL + DEVIATION_RED))
   and    (msDiff >= (MOD_INTERVAL - DEVIATION_RED)) then
    newColor := clBlack
  else
    newColor := clRed;
  try
    lbl.Font.Color := newColor;
    lbl.Caption := newValue;
  except
  end;
end;

end.

效果不如原始过程那么强烈,但可以重现。 如果一个人开始 180 你可以看到同样的效果只是减速不是那么严重。

8 月 4 日更新: 我添加了 WPA-Analyze-Session 的屏幕截图。在这里可以看到顺序。从鼠标在 Window 上开始,然后是桌面,Window,桌面,鼠标在 Window 上结束。 您可以看到,如果鼠标在桌面上,Thread: CSwitch 计数将减少近一半。您还可以看到,系统负载始终在 10-17% 之间。

在我们设法将调试符号添加到我们的一些进程之后,我们在 Delphi-VCL/Forms.pas 中发现了问题。 在新的跟踪中,使用调试符号,我们看到 Application.DoMouseIdle 方法花费大量时间查找 VCLWindows、获取这些窗口的父级等等。 减速的根源是“FindDragTarget”方法。我们的流程不需要拖放功能,也不需要在某处显示提示。所以我们从代码中删除了这个函数调用,这并不容易。 现在一切都运行快速脱离鼠标位置。