delphi - CalcFields 导致堆栈溢出

标签 delphi stack-overflow

使用 Delphi 2005,我有一个 TwwDBGrid (InfoPower),它允许用户选择零件和数量来生成报价。选择过程的一部分是允许用户为由 DiscountAmount 和 DiscountType 组成的每个部分添加折扣。 DiscountAmount 是折扣金额,DiscountType 是折扣金额类型(% 折扣、$ 折扣或统一价格)。此数据保存在名为 ClientDataSetParts 的 ClientDataSet 中。

在 OnCalc 方法 (ClientDataSetPartsCalcFields) 中,我有以下代码,它将根据零件成本和任何折扣重新计算 TotalPrice。 RangePricing 用于根据范围内的数量计算价格的情况(即 1-100 = $100、101-200 = $150 等):

procedure TfrmCustom_Services.ClientDataSetPartsCalcFields(
  DataSet: TDataSet);
begin
  inherited;
  // if part is selected then calculate Total
  if (ClientDataSetPartsSelected.Value) then begin
    // if range pricing is defined
    if (ClientDataSetParts.FieldByName('RangePricing').AsBoolean) then begin
      ClientDataSetParts.FieldByName('TotalPrice').Value :=
            ClientDataSetParts.FieldbyName('UnitPrice').Value;
    // otherwise use regular pricing
    end else begin
      ClientDataSetParts.FieldByName('TotalPrice').Value :=
          ClientDataSetParts.FieldbyName('UnitPrice').Value *
          ClientDataSetParts.FieldByName('Quantity').Value;
    end;

  // otherwise clear the Total
  end else begin
    ClientDataSetParts.FieldByName('TotalPrice').Clear;
    if (ClientDataSetParts.FieldByName('Quantity').Value <> null) then
      ClientDataSetParts.FieldByName('Quantity').Clear;
    if (ClientDataSetParts.FieldByName('DiscountAmount').Value <> null) then
      ClientDataSetParts.FieldByName('DiscountAmount').Clear;
    if (ClientDataSetParts.FieldByName('DiscountType').Value <> null) then
      ClientDataSetParts.FieldByName('DiscountType').Clear;
  end;

  // Update totals if Discount is applied
  // Only recalculate if both discount value and type are applied
  // otherwise will constantly get errors when switching fields
  if ((ClientDataSetPartsDiscountAmount.Value > 0) and (ClientDataSetPartsDiscountType.Value <> '')) then begin
    case StringToCaseSelect((ClientDataSetPartsDiscountType.Value), ['% Disc','$ Disc','Price']) of
      0 :
      begin
        ClientDataSetParts.FieldByName('DiscountDollarAmount').Value :=
            ClientDataSetParts.FieldByName('TotalPrice').Value * (ClientDataSetParts.FieldByName('DiscountAmount').Value/100);
        ClientDataSetPartsTotalPrice.Value := ClientDataSetPartsTotalPrice.Value - (ClientDataSetPartsTotalPrice.Value * (ClientDataSetPartsDiscountAmount.Value/100));
      end;
      1 :
      begin
        ClientDataSetParts.FieldByName('DiscountDollarAmount').Value := ClientDataSetPartsDiscountAmount.Value;
        ClientDataSetPartsTotalPrice.Value := ClientDataSetPartsTotalPrice.Value - ClientDataSetPartsDiscountAmount.Value;
      end;
      2 :
      begin
        ClientDataSetParts.FieldByName('DiscountDollarAmount').Value :=
            ClientDataSetPartsTotalPrice.Value - ClientDataSetPartsDiscountAmount.Value;
        ClientDataSetPartsTotalPrice.Value := ClientDataSetPartsDiscountAmount.Value;
      end;
    end;
  end;

end;

当我尝试计算 DiscountDollarAmount(我必须通过 API 返回到外部源的折扣的实际美元金额)时,问题就出现了。每次我设置 ClientDataSetParts.FieldByName('DiscountDollarAmount').Value 时,都会再次调用 ClientDataSetPartsCalcFields ,从而导致无休止的调用并最终导致堆栈溢出。

如何在不递归调用 ClientDataSetPartsCalcFields 的情况下更新此值?

最佳答案

您进入的无限循环是由代码更改值、看到它已更改并重新开始更改(如您所知)引起的。要解决此问题,请在过程开始时将 OnCalc 事件设置为 nil,然后在结束时将其重新设置为过程。这样,事件监控将在实际处理期间暂停,然后在处理完成并分配新值后恢复。

关于delphi - CalcFields 导致堆栈溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12935503/

相关文章:

delphi - 如何通过 https 使用 IdHTTP 下载有进度的文件

javascript - 为什么 Javascript 中的递归异步函数会导致堆栈溢出?

java - 递归方法中的堆栈溢出错误

java - 编写此递归函数的另一种方法?

java - 子类的构造函数中的堆栈溢出错误

delphi - 如何使用一个命令将滚动条夹点发送到最顶部位置?

delphi - 我可以更改监视列表中字符串的显示格式吗?

delphi - 避免在 Delphi XE2 下对元素进行蒙皮

Delphi 7从路径获取文件夹名称

c - 缓冲区溢出的编译器艺术