0

I do some reporting on a form with reportbuilder. On the main form I select some items on a grid and then a generate the reports of the items. I want to do this in a Tthread but i get an error 'List index out of bounds'.

Here is the call stack:

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

Seems some form is either not being added to the Screen.Forms collection in a timely manner or one is being freed from it during the loop in DoActionIdle.

Any ideas on how to circumvent this problem? I work on windows XP and delphi 2010.

I Also I've the problem with a test procedure on my application TForm3 is just a form with no code.

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;

Recapitulation:

I have a list of some Intervention on a form. Each detail and resumation of the intervention can I print on 2/5 reports. Therefore I use reports components (reportbuilder) on another form (not visible). The new feature was to multiselect some interventions on the list and set the reports in a folder in pdf format. That's was simple just on each intervention call the reportform and some parameters to change and save into pdf. But this take to long. The user must wait until the procedure was ended. No problem I set the procedure in a thread. But there I get the error 'List index out of bounds'. ArgggArggg, I was suspected that the reportform (created, to his job and then destroyed) the problem was but hoped that there was another solution. I was thinking to change the TForm into TDataModule. Can I set all the components of the form into the datamodule. I use the TDbGrid to see some values in design. But in the Tdatamodule I can't set a TDBGrid. Ok, I can live without the TDbGrid. So I transformed the TForm into TDataModule. But the TDataModule is not the answer. There I get the error 'Graphics.OutOfResource' from a TBitmap. I think that the TBitmap is calling from the TppReport. Now I'm done. I'm changing my code all more than 2 days with no result. I leave the TThread for this time.

Ravaut123
  • 2,764
  • 31
  • 46
  • A couple of comments. You've asked two completely different unrelated questions here. You should ask one question at a time. And secondly you've not actually said what the problem is with the second part of your question. You just said "I've the problem" which is really too vague. You need to explain what the problem is. – David Heffernan Mar 19 '13 at 15:05
  • @DavidHeffernan: It just the same error. I eliminate some code to catch the error in the procedure DoActionIdle. The error i get is 'Items out of bounds'. The screen.customformcount is changing in the loop – Ravaut123 Mar 19 '13 at 15:40
  • OK, I failed to infer that. Anyway, I think everything I said in the answer stands. – David Heffernan Mar 19 '13 at 15:43

1 Answers1

2

Let's take a look at 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;

Let's assume that Screen.CustomFormCount and is implemented correctly and always returns the number of items indexed by Screen.CustomForms. In which case the conclusion is that the body of the loop is deleting a form. That is Screen.CustomFormCount is changing during the execution of the loop.

The only way that can happen is if one of the form's action update handlers results in a form being deleted. So, I can't tell you any more than that, but this analysis should lead you to the root cause of the problem.


And the second part of your question is quite simple. You cannot use VCL components outside the main GUI thread.

In fact it is plausible that destroying the VCL form in your thread is what is leading to Screen.CustomFormCount changing during the execution in the GUI thread of TApplication.DoActionIdle.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490