如何使用onchange事件创建Tstrings?

时间:2015-07-24 15:59:21

标签: delphi delphi-xe7

我知道怎么做Tstringlist onchange事件,但是Tstrings怎么样?我不想像tmemo或其他东西一样使用VCL。我能这样做吗?是否有可能在tstrings上发生这个事件并在改变时做一些事情?

我试图做类似这样的事情,但遭到访问违规

//on form show event
   stringlist:= TStringList.Create;
  stringlist.OnChange := HandleStringListChange;
//implantation 
    procedure TChatFo.HandleStringListChange(Sender: tObject);
    begin
    if stringlist.Text <> '' then
    ProcessCommands(stringlist.Text);
    stringlist.Clear;
    end;

异常消息

  

Project Project1.exe引发了带有消息的异常类$ C0000005   &#39;访问违规行为0x6d40c92c:读取地址0x00000150&#39;。

     

Project Project1.exe引发了异常类EStringListError   消息&#39;列出索引越界(5)&#39;。

     

Project Project1.exe引发了异常类EStringListError   消息&#39;列出索引越界(5)&#39;。

这个tstringlist应该作为命令标识符使用我的线程

创建它

例如

  TReadingThread = class(TThread)
  protected
    FConnection  : TIdTCPConnection;
    FLogResult   : TStrings;
    procedure Execute; override;
  public
    constructor Create(AConn: TIdTCPConnection; ALogResult: TStrings); reintroduce;
  end;

ListeningThread := TReadingThread.Create( TCPClient, stringlist);



constructor TReadingThread.Create(AConn: TIdTCPConnection; ALogResult: TStrings);
begin
  FConnection := AConn;
  FLogResult  := ALogResult;
  inherited Create(False);
end;


procedure TReadingThread.Execute;
Var
  strData : String;
begin
  while not Terminated do
  begin
    try
      strData := FConnection.IOHandler.ReadLn;
      if strData <> '' then
      begin
        FLogResult.Add( strData );
      end;
    except
      on E: Exception do
      begin
        FConnection.Disconnect(False);
        if FConnection.IOHandler <> nil
          then FConnection.IOHandler.InputBuffer.Clear;
        Break;
      end;
    end;
    Sleep(10);
  end; // While
end;

如果我使用Tmemo没有错误或发生异常。

3 个答案:

答案 0 :(得分:2)

我们所有人都在黑暗中拍摄,因为您还没有提供所有相关代码。也就是说,您提供的信息存在很多问题,我可以提供建议来帮助您解决问题。

调试101

通过IDE运行代码。当您收到异常时,调试器将在导致异常的行停止 这通常是找出问题的最重要步骤。您可以访问此信息。运行程序并仔细查看引发错误的行。您可能已经能够确定导致错误的原因。如果没有,可以应用其他基本技术来获取更多信息:

  • 获取错误行和其他关闭行上的对象和变量的值。您可以将鼠标光标悬停以获取工具提示,或按 Ctrl + F7
  • 您可以通过双击调用堆栈中的上一行来检查导致错误的行的调用堆栈。
  • 在错误发生前的行上放置断点并重新运行应用程序。调试器将在该行停止,并让您有机会按照前面的说明检查值,但之前错误发生。

寻求帮助101

当您向他们提供所有相关信息时,获得人们的帮助会更有效。首先,发生访问冲突的代码行非常有用....告诉我们!

给我们真实代码 说&#34;我试图做这样的事情&#34;不是特别有用。请复制并 粘贴 。如果您的代码不同,您的错误可能不再存在。

访问冲突

在以下情况下,您会收到访问冲突:

  • 您忘了创建要使用的对象,或者没有将其分配给相应的变量。
  • 您创建了该对象,但在尝试再次使用之前已经Destroy ed或Free d。
  • 您更改了引用该对象的变量。
  • 你进行了一场“强硬表演”。 (或未经检查的类型转换)从一种类型到不兼容的类型。
  • 以上是基础知识。有一些变化,以及一些特殊的边缘情况,但这些都是绝大多数错误的原因。

因此,使用上述内容,您需要检查的内容。如果您复制了 粘贴 更多代码,我们可能会看到您做错了什么。

注意:一个黑暗中的可能性是你在错误的地方销毁你的字符串列表。也许备忘录有效,因为作为一个组件放在表单上,​​你不会试图破坏它。

堆栈溢出

让我们检查一下你的OnChange事件会发生什么变化,例如添加一个字符串:

  • 事件发生。
  • Text不为空。
  • 所以你打电话给ProcessCommands
  • 然后致电Clear
  • 再次调用ClearChanged的结尾。
  • 再次激发你的活动。
  • 这一次Text为空,因此您无法致电ProcessCommands
  • 但你确实再次尝试Clear字符串列表......
  • 这可以永远持续下去;好吧,至少在调用堆栈用完空间并且出现堆栈溢出错误之前。

通过铃声保存

您没有获得堆栈溢出的唯一原因是,如果字符串列表为空,Clear不会执行任何操作:

procedure TStringList.Clear;
begin
  if FCount <> 0 then //You're lucky these 2 lines stop your stack-overflow
  begin
    ...
    FCount := 0;      //You're lucky these 2 lines stop your stack-overflow
    SetCapacity(0);
    Changed;
  end;
end;

我建议你重新考虑如何解决你的问题,因为导致无意递归的代码会让你的生活变得困难。

使用线程

在尝试使用线程之前,您确实需要掌握编程的基础知识。多线程编程会带来很大的复杂性。

我已经看到了一个潜在错误的巨大可能性。 (虽然这取决于你在ProcessCommands内做了什么。)

  • 您可以在线程的上下文中修改字符串列表。
  • 这意味着您的OnChange事件处理程序也会在线程的上下文中触发。 (它在表单上实现的事实无关紧要。
  • 如果您的ProcessCommands方法执行任何需要它在主线程上运行的方法,那么您遇到问题。

作为最后的考虑,我注意到很多初学程序员完全忽略了启动一个线程的代码可以在线程之前完成的点。例如。 (回到有关访问冲突的主题。):如果您在创建线程后立即销毁字符串列表,那么当前一个对象突然消失时,您的线程可能会突然抛出访问冲突。

答案 1 :(得分:1)

您错误的可能解释是您正在修改其OnChange事件处理程序中的列表。这根本不允许。 OnChange处理程序不得改变对象的状态。

发生的事情是你有一些其他代码,我们看不到,它修改了列表,也许是在一个循环中。当它修改列表时,你的事件处理程序会清除列表,然后调用代码就会从它下面拉出地毯。

当然,我不得不在这里猜测,因为你没有显示完整的代码。也许具体情况有所不同,但似乎这可能是你问题的根源。

您需要找到另一种方法来解决您的问题。有了这些信息,我们无法建议如何做到这一点。

查看更新的代码,根本不需要字符串列表。完全删除它。相反,你去的地方:

FLogResult.Add( strData );

这样做:

ProcessCommands( strData );

答案 2 :(得分:0)

TStrings是一个抽象类,TStringList的祖先。您可以创建TStringList的实例,并将其用作TStrings