Performanceissue with TImageList
Update: This problem is solved with Delphi 10.1 Berlin
(Deutsche übersetzung im nachfolgenden Blog Eintrag)
Description of the problem:
Adding pictures to a Imagelist within a VCL application is very slow after a the change to Delphi 10 Seattle.
Usually adding pictures is very fast – as long as you act like this:
... iml: TImageList; ... iml.BeginUpdate; try for x in BigList do begin iml.Add(x); end; finally iml.EndUpdate; end;
One reason for a long time to add many pictures is, that clients of the imagelist get informed about every change on the list. To send this information just once and just at the end of all inserts we use BeginUpdate and EndUpdate.
This BeginUpdate and EndUpdate does not work like it should with Delphi 10 Seattle.
To understand this we look at the source coude:
Inheritance ot the TImageList:
Base is TBaseImageList in System.ImageList.
For FMX in Unit FMX.ImgList we have TCustomImageList >> TImageList
For VCL according in Unit VCL.ImgList: TCustomImageList >> TImageList
The methods BeginUpdate and EndUpdate in the base class looks like this:
procedure TBaseImageList.BeginUpdate; begin if FUpdateCount = 0 then Updating; Inc(FUpdateCount); end; procedure TBaseImageList.EndUpdate; begin if FUpdateCount > 0 then begin Dec(FUpdateCount); if FUpdateCount = 0 then Updated; end; end;
Both methods does what we expect.
Unfortunately the class TCustomImageList overwrite this for VCL (not override, not virtual!):
procedure TCustomImageList.BeginUpdate; begin Inc(FUpdateCount); end; procedure TCustomImageList.EndUpdate; begin if FUpdateCount > 0 then Dec(FUpdateCount); if FChanged then begin FChanged := False; Change; end; end;
Updateing and Updated is not set anymore. UpdateCount is reintroduced and is not used further. The change method of the base class will call DoChange on every add – our BeginUpdate does not have effect.
Comparison to older sources of the VCL show that something went wrong here.
The solution of this problem indeed is easy: We just use the „good“ method of the base class.
Only problem: You have to check on further delphi versions, if there are may changes in the VCL method, which we do not want to skip, cause we do not execute them from now on.
I think this dephi bug will be solved in future – so we can go back to the original code.
... iml: TImageList; ... TBaseImageList(iml).BeginUpdate; try for x in BigList do begin iml.Add(x); end; finally TBaseImageList(iml).EndUpdate; end;