在screen.forms上列出索引超出界限

时间:2013-03-19 13:21:48

标签: multithreading delphi delphi-2010

我使用reportbuilder对表单进行一些报告。 在主窗体上,我选择网格上的一些项目,然后生成项目的报告。 我想在Tthread中执行此操作,但我收到错误'List index out of bounds'。

这是调用堆栈:

Classes.TList.Get(1244868)
Classes.TList.Get(???)
Forms.TScreen.GetCustomForms(???)
Forms.TApplication.DoActionIdle
Forms.TApplication.Idle(???)
Forms.TApplication.HandleMessage
Forms.TApplication.Run

似乎某些表单未添加到Screen.Forms中 及时收集或者在收集期间从中收集 在DoActionIdle中循环。

关于如何规避这个问题的任何想法? 我在Windows XP和delphi 2010上工作。

我还有我的应用程序测试程序的问题 TForm3只是一个没有代码的表单。

TDebugThread = class(TThread)
protected
  procedure Execute; override;
public
  constructor Create();
end;

constructor TDebugThread.Create;
begin
   FreeOnTerminate := True;
   inherited Create(False);
end;

procedure TDebugThread.Execute;
var
  oReport:  DeBugReport.TForm3;
begin
  inherited;
  oReport:=  DeBugReport.TForm3.Create(Nil);
  try
    sleep(1000);
  finally
    oReport.Free;
  end;
end;

....
procedure RunThread();
begin
  TDebugThread.Create();
end;

重演:

我在表格上列出了一些干预措施。我可以在2/5报告上打印干预的每个细节和结果。因此,我在另一个表单(不可见)上使用报表组件(reportbuilder)。新功能是在列表中多选一些干预措施,并将报告设置为pdf格式的文件夹。这很简单,只需在每次干预时调用reportform和一些参数来更改并保存为pdf。 但这需要很长时间。用户必须等到程序结束。没问题我在一个线程中设置了该过程。但在那里我得到错误'列表索引超出范围'。 ArgggArggg,我怀疑报告形式(创建,他的工作,然后销毁)问题,但希望有另一个解决方案。我当时想把TForm改成TDataModule。我可以将表单的所有组件都设置为数据模块。我使用TDbGrid来查看设计中的一些值。但是在Tdatamodule我无法设置TDBGrid。好吧,我可以没有TDbGrid。所以我把TForm变成了TDataModule。 但是TDataModule不是答案。在那里我从TBitmap得到错误'Graphics.OutOfResource'。我认为TBitmap是从TppReport调用的。现在我已经完成了。我正在更改我的代码超过2天没有结果。我这次离开了TThread。

1 个答案:

答案 0 :(得分:2)

我们来看看TApplication.DoActionIdle

procedure TApplication.DoActionIdle;
var
  I: Integer;
begin
  for I := 0 to Screen.CustomFormCount - 1 do
    with Screen.CustomForms[I] do
      if HandleAllocated and IsWindowVisible(Handle) and
        IsWindowEnabled(Handle) then
        UpdateActions;
end;

我们假设Screen.CustomFormCount并且正确实现并始终返回由Screen.CustomForms索引的项目数。在这种情况下,结论是循环体正在删除一个表格。那是Screen.CustomFormCount在执行循环期间正在改变。

唯一可能发生的方法是,如果表单的某个操作更新处理程序导致表单被删除。所以,我不能告诉你更多,但这种分析应该引导你找出问题的根本原因。


问题的第二部分非常简单。您不能在主GUI线程之外使用VCL组件。

事实上,在你的线程中销毁VCL表单是导致Screen.CustomFormCountTApplication.DoActionIdle的GUI线程中执行期间发生变化的原因。