【问题标题】:Strange behavior using TPointSeries.Clear使用 TPointSeries.Clear 的奇怪行为
【发布时间】:2016-03-16 00:04:33
【问题描述】:

(Delphi 6 与 TChart,Win XP)

我在尝试清除点系列中的点时出现了不稳定的行为,当然,这段代码曾经可以工作。

基本上,我的程序的这一部分会生成 5 个数据点并绘制它们。当我尝试使用 OSC_Series.Clear 清除它们时,出现“列表索引超出范围 [0]”错误。

我检查以确保我绘制的值没有任何奇怪之处。那里一切都很好。然后我尝试了不同的方法来尝试隔离和解决问题。

这是一些代码。

type
  TksGraph_DataFrm = class(TForm)
  .
  .
  .
  private
    OSC_Series: TPointSeries
  public
  end;

procedure TksGraph_DataFrm.cat7AnalysisInitialize(var P:TTest_Project);
begin

  // Do a bunch of stuff.

  // Set up the analysis data points series.
  OSC_Series:=TPointSeries.Create(self);
  AnalysisChart.AddSeries(OSC_Series);
  with OSC_Series do
  begin
    Title:='';
    HorizAxis:=aBothHorizAxis;
    VertAxis:=aBothVertAxis;
    SeriesColor:=clRed;
    Pointer.Brush.Color:=clYellow;
    Pointer.HorizSize:=4;
    Pointer.VertSize:=4;
    Pointer.Style:=psRectangle;
    Pointer.Visible:=true;
    LinePen.Color:=clBlack;
    LinePen.Width:=1;
    Linepen.Visible:=true;
    ShowInLegend:=false;
    XValues.Order:=LoNone;
  end;
end;

procedure TksGraph_DataFrm.cat7AnalysisRefresh(var P:TTest_Project);
var X,Y:single;
begin

  X:= some value
  Y:= some value

  // Plot the result.
  OSC_Series.AddXY(X,Y);
  showmessage(
    'Count = '+inttostr(OSC_Series.Count)+#13+
    'X = '+FloatToStr(X)+#13+
    'Y = '+FloatToStr(Y)+#13+
    'Plot-X = '+FloatToStr(OSC_Series.XValue[OSC_Series.Count-1])+#13+
    'Plot-Y = '+FloatToStr(OSC_Series.YValue[OSC_Series.Count-1]));

end;

这是我用来重置系列的例程。我包含了有效和无效的代码。

procedure TksGraph_DataFrm.cat7AnalysisClear(var P:TTest_Project);
var i:integer;
begin

  // This should work, but it gives me the list out of bounds error
  // unless the count is 0.
  OSC_Series.Clear;

  // This does not work, for obvious reasons. I get a "list out of 
  // bounds [3] for this one.
  for i:=0 to OSC_Series.Count - 1 do OSC_Series.Delete[0];

  // It seems this should work, but again I get the out of bounds [0]  
  // error.
  repeat
    OSC_Series.Delete(0);
  until OSC_Series.Count = 0;

  // This works. Don't ask me why.
  showmessage('A - '+inttostr(OSC_Series.Count));
  OSC_Series.Clear;
  showmessage('B - '+inttostr(OSC_Series.Count));

  // This also works.
  sleep(2000);
  OSC_Series.Clear;

  // This does not work.
  sleep(1000);
  OSC_Series.Clear;

end;

显然,我被难住了。

【问题讨论】:

  • 请出示minimal reproducible example或做一些调试
  • 你使用单线程吗?你能确定 OSC_Series 是从同一个线程操作的吗?
  • 您使用的是 Delphi 6 附带的 TeeChart Standard 版本吗?我无法在 RAD XE 中重现最新版本 v2015.16 的问题。在我的测试应用程序中,我只是在一个新表单上放置了一个 TChart 和一个 TButton。我在OnCreate 创建了OSC_Series,并在我的Button1Click 中调用了来自您的cat7AnalysisClear 的代码。在每次“清除尝试”之前我也会打电话给OSC_Series.FillSampleValues(); 来检查它(我没有使用你的cat7AnalysisRefresh
  • 这里不涉及线程。
  • Series.Clear 可以在其他任何地方使用,因此在 TeeChart 中不太可能出现问题。我将该系列重命名为 OCS_SeriesA,但这并没有帮助。我将其引用为 Self.OSC_Series,没有变化。我认为将系列名称与另一个系列名称混淆的问题已经解决。我尝试将代码放在 try... except 块中,EurekaLog 在我的代码之前抓取它。只有在 Series.Delete(0) 和 while 语句之间有 ShowMessage 行时,repeat..until 代码才有效。 ShowMessage 行试图告诉我一些事情。

标签: delphi teechart delphi-6


【解决方案1】:

这听起来像是代码正在处理一个已被破坏的对象 (OSC_Series),然后内存又被重新用于其他用途。然后,当您使用对该内存的陈旧引用时,您会得到意想不到和不可预测的结果。

OSC_Seriesfree'd 在哪里?

我会检查所有这些地方,并确保您在释放 OSC_Series 引用后不要尝试使用它。

另请注意,由于该系列归表单所有,因此可能是表单本身在销毁其拥有的组件(包括该系列)后试图在事件中执行代码。 p>

【讨论】:

  • 谢谢。我检查了那个。这个变量是这种形式的局部变量,也是另一种形式的变量。全局搜索不会显示它在其他任何地方被引用。 OSC_Series 在窗体关闭时被释放。 (我在 EurekaLog 中打开了内存泄漏检测。)我唯一一次遇到这样的问题是当我关闭范围检查并且我正在覆盖内存时。
【解决方案2】:

好吧,笨而不笨。

我尝试了放置 showmessage 语句的位置。我发现如果该语句出现在 OSC_Series.Clear 语句之后,我只能避免该错误。我一直将那个语句移回,直到它在调用 AnalysisRefresh 例程之后,该例程位于按钮的 OnClick 事件处理程序中。这意味着刷新、启用或更新例程中的任何代码都没有导致这种情况。

后退一步,如果 AnalysisRefresh 例程失败,则会向用户显示一条消息。关闭该框后,将调用 OSC_Series.Clear。如果我通过按键盘上的 SPACE 或 ENTER 关闭该框...没有错误。如果我使用鼠标,则会出错。

鼠标后面的图表有一个 OnMouseMove 事件,我在状态栏上显示鼠标位置。如果鼠标靠近绘图点,我也会显示提示。用鼠标单击消息框以将其关闭后,将调用 OnMouseMove 事件,当它到达可以显示提示的位置时,绘图点已消失,并且...错误。

所以,这似乎是一个几乎随机的错误,但事实并非如此。触发器完全在其他地方。那是你我的 try/except 块没有发现错误。 EurekaLog 正在捕捉它,但在很远很远的地方采用不同的程序。 (Deltics 的回答非常接近。)

感谢您的帮助和建议。

如果有一天我可以毫无问题地推送数百行代码,那么该死的,然后会弹出类似的东西,并且花费了我将近两天的时间。

【讨论】:

  • 这感觉就像一个“亲爱的日记”条目。您在这里谈论的任何内容都与问题中的细节无关。在你有一个明确的问题陈述之前,你不应该问这个问题。您应该刚刚调试了您的程序。你做了什么。一旦你隔离了问题,答案就很明显了。
  • 那么,还不够神秘吗?我认为描述我是如何发现问题的至少与描述我的发现一样有用。我为此工作了一天多,被难住了。一切都指向了清除系列的问题。我在这里和其他地方搜索类似的问题。一无所获,我在这里发帖,但我没有放弃。问题结果与 Deltic 所说的类似,即其他代码试图使用该系列。
  • 没有。恰恰相反。这个问题太模糊了,从一个谈论问题中没有的事情的答案中可以看出。
  • “基本上,我的这部分程序会生成 5 个数据点并绘制它们。当我尝试使用 OSC_Series.Clear 清除它们时,我收到“列表索引超出范围 [0]”错误。”我随后用代码示例展示了我为将问题隔离到一行代码所做的工作,然后执行看似不相关的事情(显示消息和睡眠)似乎消除了问题。这没有任何意义。我被难住了。我问是否有人见过类似的东西。
  • 是的。我告诉你,这不是一个好问题。我不希望你同意我的看法。
猜你喜欢
  • 2019-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-10
  • 2010-10-28
  • 2020-06-24
相关资源
最近更新 更多