0

我用reportbuilder在表格上做一些报告。在主窗体上,我在网格上选择了一些项目,然后生成项目的报告。我想在 Tthread 中执行此操作,但出现错误“列表索引超出范围”。

这是调用堆栈:

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 格式的文件夹。这很简单,只需在每次干预时调用报告表和一些要更改并保存为 pdf 的参数。但这需要很长时间。用户必须等到程序结束。没问题我在一个线程中设置程序。但是我收到错误“列表索引超出范围”。ArgggArggg,我怀疑报告表(创建,他的工作,然后销毁)的问题,但希望有另一种解决方案。我正在考虑将 TForm 更改为 TDataModule。我可以将表单的所有组件设置到数据模块中吗?我使用 TDbGrid 来查看设计中的一些值。但是在 Tdatamodule 中我无法设置 TDBGrid。好的,我可以没有 TDbGrid。所以我将 TForm 转换为 TDataModule。但 TDataModule 不是答案。在那里,我从 TBitmap 收到错误“Graphics.OutOfResource”。我认为 TBitmap 是从 TppReport 调用的。现在我完成了。我更改代码超过 2 天都没有结果。这次我离开了 TThread。我认为 TBitmap 是从 TppReport 调用的。现在我完成了。我更改代码超过 2 天都没有结果。这次我离开了 TThread。我认为 TBitmap 是从 TppReport 调用的。现在我完成了。我更改代码超过 2 天都没有结果。这次我离开了 TThread。

4

1 回答 1

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.CustomFormCountand 被正确实现并且总是返回由 索引的项目数Screen.CustomForms。在这种情况下,结论是循环体正在删除一个表单。那是Screen.CustomFormCount在循环执行期间发生变化。

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


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

事实上,在你的线程中破坏 VCL 表单是Screen.CustomFormCount导致TApplication.DoActionIdle.

于 2013-03-19T13:31:30.817 回答