在delphi中重构慢函数

时间:2015-08-17 02:19:07

标签: multithreading delphi delphi-xe

我正在重构一个旧的应用程序,使其响应更快,我有一个使用devExpress组件的表单,并使用CallbackCustomDrawPreviewCell创建一个自定义网格,问题是这个函数非常慢,需要大约0.09s每次通话,但每次打开表格时调用约30至60次,因此表格可以打开2.8秒到5.6秒。 我通常使用C#和Object-C / Swift进行编程,我们可以在后台发送一个块进行处理,但就我的研究而言,我们在Delphi中没有类似的东西,似乎通常在Delphi中有一个新线程必须是一个全新的独立代码。我的假设是否正确?

如果是这样,在这种情况下提高速度的最佳解决方案是什么? (我正在使用Delphi XE)

(如果它有帮助:我也刚刚买了AQTime试图帮我弄清楚如何改进这个但是到目前为止我没有运气,还需要多深入挖掘手册。但它确实对我有所帮助在这个特定的回调中找到速度问题)

提前致谢。

功能是:

procedure TtvdAvaOutageManagementForm.CallbackCustomDrawPreviewCell(Sender: TcxCustomTreeList; ACanvas: TcxCanvas;
  AViewInfo: TcxTreeListEditCellViewInfo; var ADone: Boolean);
const
  AlignFlag = DT_LEFT or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX or DT_END_ELLIPSIS;
  cnFontColor = clBlue;
var
  AFaultId: variant;
  aFault: TtvdFault;
  aLocalities, aFaultLocalities: TStringList;
  i: integer;
  aLocality: string;
  Rect: TRect;
  size: TSize;
  AText: string;
begin
  { colour the preview text blue }
  ACanvas.Font.Color := cnFontColor;
  AText := AViewInfo.DisplayValue;
  aLocalities := TStringList.Create;
  aFaultLocalities := TStringList.Create;
  try
    AFaultId := AViewInfo.Node.Values[FtvdTree.GetColumnByFieldName('FaultId').ItemIndex];
    if (not VarIsNull(AFaultId)) then
    begin
      ACanvas.Brush.Color := COLOR_FAULT;

      aFault := FtvdFaults.tvdGetFault(AFaultId);
      if Assigned(aFault) then
      begin
        ACanvas.Brush.Color := aFault.tvdFaultColor;

        ACanvas.Brush.Color := aFault.tvdFaultColor;
        ACanvas.FillRect(AViewInfo.BoundsRect);
        CopyRect(Rect, AViewInfo.BoundsRect);
        InflateRect(Rect, -1, -1);
        Inc(Rect.Left, FtvdTree.OptionsView.IndicatorWidth);
        ACanvas.Font.Color := cnFontColor;

        { if all the localities are in the fault then bold the preview text,
          else need to do it manually (i.e. only bold the localities that are
          in the fault }
        if aFault.tvdAllLocalities then
        begin
          ACanvas.Font.Style := [fsBold];
          ACanvas.DrawTexT(AText, AViewInfo.BoundsRect, AlignFlag);
        end
        else
        begin
          CopyRect(Rect, AViewInfo.BoundsRect);

          aLocalities.Text := StringReplace(AText, ', ', #13#10, [rfReplaceAll]);
          aFaultLocalities.Text := StringReplace(aFault.tvdLocalities, ', ', #13#10, [rfReplaceAll]);
          for i := 0 to aLocalities.Count - 1 do
          begin
            ACanvas.Font.Style := [];
            { draw a comma if this is not the first locality }
            if i > 0 then
            begin
              size := ACanvas.TextExtent(',');
              DrawText(ACanvas.Handle, ',', 1, Rect, DT_LEFT or DT_NOPREFIX);
              Inc(Rect.Left, size.cx);
            end;

            aLocality := aLocalities[i];
            if aFaultLocalities.IndexOf(aLocality) >= 0 then
            begin
              ACanvas.Font.Style := [fsBold];
            end;

            size := ACanvas.TextExtent(aLocality);
            if (Rect.Left + size.cx) > Rect.Right then
            begin
              Rect.Left := AViewInfo.BoundsRect.Left;
              Inc(Rect.Top, size.cy);
            end;

            { draw the text item }
            DrawText(ACanvas.Handle, pchar(aLocality), Length(aLocality), Rect, DT_LEFT or DT_NOPREFIX);
            Inc(Rect.Left, size.cx);
          end;
        end;

        ADone := true;
      end;
    end;

  finally
    aLocalities.Free;
    aFaultLocalities.Free;
  end;
end;

1 个答案:

答案 0 :(得分:1)

如果你总结我的评论那么它应该或多或少。

试着告诉我们它是如何为您解决的。由于我没有一个有效的例子,它可能不是100%正确。

procedure TtvdAvaOutageManagementForm.CallbackCustomDrawPreviewCell(Sender: TcxCustomTreeList; ACanvas: TcxCanvas;
  AViewInfo: TcxTreeListEditCellViewInfo; var ADone: Boolean);
const
  AlignFlag = DT_LEFT or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX or DT_END_ELLIPSIS;
  cnFontColor = clBlue;
var
  AFaultId: variant;
  aFault: TtvdFault;
  aLocalities, aFaultLocalities: TStringList;
  i: integer;
  aLocality: string;
  Rect: TRect;
  size: TSize;
  AText: string;
begin
  { colour the preview text blue }
  ACanvas.Font.Color := cnFontColor;
  AText := AViewInfo.DisplayValue;
  aLocalities := TStringList.Create;
  aFaultLocalities := TStringList.Create;
  try
    AFaultId := AViewInfo.Node.Values[FaultIdColumn.ItemIndex];
    if not VarIsNull(AFaultId) then
    begin
      ACanvas.Brush.Color := COLOR_FAULT;    
      aFault := FtvdFaults.tvdGetFault(AFaultId);

      if Assigned(aFault) then
      begin
        ACanvas.Brush.Color := aFault.tvdFaultColor;

        ACanvas.Brush.Color := aFault.tvdFaultColor;
        ACanvas.FillRect(AViewInfo.BoundsRect);
        CopyRect(Rect, AViewInfo.BoundsRect);
        InflateRect(Rect, -1, -1);
        Inc(Rect.Left, FtvdTree.OptionsView.IndicatorWidth);
        ACanvas.Font.Color := cnFontColor;

        { if all the localities are in the fault then bold the preview text,
          else need to do it manually (i.e. only bold the localities that are
          in the fault }

        if aFault.tvdAllLocalities then
        begin
          ACanvas.Font.Style := [fsBold];
          ACanvas.DrawTexT(AText, AViewInfo.BoundsRect, AlignFlag);
        end
        else
        begin
          CopyRect(Rect, AViewInfo.BoundsRect);

          aLocalities.CommaText:= AText;

          aFaultLocalities.CommaText := aFault.tvdLocalities;
          aFaultLocalities.Sorted := True;

          for i := 0 to aLocalities.Count - 1 do
          begin
            ACanvas.Font.Style := [];
            { draw a comma if this is not the first locality }
            if i > 0 then
            begin
              size := ACanvas.TextExtent(',');
              DrawText(ACanvas.Handle, ', ', 1, Rect, DT_LEFT or DT_NOPREFIX);
              Inc(Rect.Left, size.cx);
            end;

            aLocality := aLocalities[i];
            if aFaultLocalities.IndexOf(aLocality) >= 0 then
            begin
              ACanvas.Font.Style := [fsBold];
            end;

            size := ACanvas.TextExtent(aLocality);
            if (Rect.Left + size.cx) > Rect.Right then
            begin
              Rect.Left := AViewInfo.BoundsRect.Left;
              Inc(Rect.Top, size.cy);
            end;

            { draw the text item }
            DrawText(ACanvas.Handle, pchar(aLocality), Length(aLocality), Rect, DT_LEFT or DT_NOPREFIX);
            Inc(Rect.Left, size.cx);
          end;
        end;

        ADone := true;
      end;
    end;

  finally
    aLocalities.Free;
    aFaultLocalities.Free;
  end;
end;