我使用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。
答案 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.CustomFormCount
在TApplication.DoActionIdle
的GUI线程中执行期间发生变化的原因。