对于这个问题,请参阅我前一段时间提出的问题:Do I need TThreads? If so can I pause, resume and stop them? LU RD通过提供的演示和一些评论回答了问题。
我已经停止使用Delphi很长一段时间了,但现在我又回到了它并重做了一个项目。该项目具有耗时的操作,例如打开Gif,提取帧然后将这些帧(位图)添加到TImageList和TListView中。这次我实际上将位图直接添加到TObjectList中,如下所示:How to add and retrieve Bitmaps to and from a TList?
通常没有什么特别的需要在这里加速,因为大多数Gif动画都很小,但是对于中到大的Gif,应用程序可以挂起。这会变得更糟,因为这些位图将在运行时使用各种成像滤镜(如灰度,更改色调等)进行修改。所以我确信我需要多线程,否则访问每个位图然后操作将会非常慢(正如我之前发现的那样)。
所以说,我愚蠢地试图适应(不知道我在做什么)我的一些程序来处理LU RD我在顶部链接的TThread示例。
我希望我花更多时间处理原始问题,以获取更多信息,但我想我已经偏离了一些东西并转移到其他东西上,这意味着我什么都没学到。
从线程示例中获取此片段:
const
cWorkLoopMax = 500;
function TForm1.HeavyWork: boolean; // True when ready
var
i, j: integer;
begin
j := 0;
for i := 0 to 10000000 do
Inc(j);
Inc(workLoopIx);
Result := (workLoopIx >= cWorkLoopMax);
end;
首先,我不知道cWorkLoopMax
是什么,为什么它的值设置为500?
其次我猜HeavyWork
程序只是一个样本,它在循环中运行10000000次,同时递增j
变量?
然后我们有workLoopIx
我不确定是什么用的?也许与线程中的位置有关?
所以,这里我有我当前的代码(没有线程)来处理打开Gif并添加到TListView和TImageList。我使用的程序在另一个单元中,如果需要我也会发布它,但这是我在TAction中使用的内容(actOpen):
if OpenPictureDialog.Execute then
begin
Screen.Cursor := crHourGlass;
try
BitmapCollection.AddFromGif(OpenPictureDialog.FileName, ImageList1);
ListView1.Items.BeginUpdate;
try
ListView1.Items.Clear;
for I := 0 to BitmapCollection.BitmapList.Count - 1 do
begin
with ListView1.Items.Add do
begin
Caption := 'bitmap' + IntToStr(I+1);
ImageIndex := I;
end;
end;
finally
ListView1.Items.EndUpdate;
end;
finally
Screen.Cursor := crDefault;
end;
end;
我不明白如何将它放入线程程序,例如HeavyWork
?我刚刚创建了一个名为Job_Open
的新工具并执行了此操作:
procedure TForm1.actOpenExecute(Sender: TObject);
begin
if OpenPictureDialog.Execute then
begin
if not Assigned(MyThread) then
begin
workLoopIx := 0;
btnStartTask.Enabled := false;
btnPauseResume.Enabled := true;
btnCancelTask.Enabled := true;
MyThread := TWorkerThread.Create(Self.Handle, WM_MyProgress, Job_Open);
end;
end;
end;
function TForm1.Job_Open: boolean;
var
I: Integer;
begin
BitmapCollection.AddFromGif(OpenPictureDialog.FileName, ImageList1);
for I := 0 to BitmapCollection.BitmapList.Count - 1 do
begin
with ListView1.Items.Add do
begin
Caption := 'bitmap' + IntToStr(I+1);
ImageIndex := I;
end;
Inc(workLoopIx);
end;
Result := (workLoopIx >= BitmapCollection.BitmapList.Count);// cWorkLoopMax);
end;
这显然不对,性能较慢,我遇到了各种错误,例如无效句柄。
如果有人能花一些时间来解释我的评论,我做错了什么以及我应该做些什么,我会非常感激,欢迎更新源代码和评论,但我希望能够学到更多理想情况下代码发生了什么。
在一个完美的世界中,如果有一个易于使用的存在的库,那么如果我无法理解上面发生的事情那将是一个巨大的帮助。是否有这样的库可以做类似的事情:
procedure DoSomething;
begin
BeginThreading();
HeavyWork;
StopThreading();
end;
提前致谢,并为漫长的帖子道歉。
答案 0 :(得分:2)
免责声明:虽然我的答案不是您问题的直接答案,但它可以解决您的问题。
在阅读完问题后,我向您提出了一个问题:
您是否在所有ImageList图像上应用相同的图像图形效果?
如果你那么我必须说你开始用错误的方法处理你的问题。
首先,您需要知道Imagelist doesen单独存储所有这些图像,但它们将它们全部存储在相同的宽幅图像中。因此,当您在内部读取任何ImageList图像时,ImageList会创建输出位图,然后使用相当的Canvas.CopyRect。将图像保存到图像列表时,它在内部使用Canvas.Draw。
因此,当您多次执行此操作时,会创建大量不必要的数据移动。
因此,我建议您使用ImageLists内部图像,而不是您处理单独图像的方法,您可以使用ImageList.GetImageBitmap获取句柄。这将使您同时对所有ImageList图像应用相同的图形效果。如果您不需要将图形效果应用于所有ImageList图像,我敢打赌您可以修改您的图像处理方法,使其仅适用于图像的某些部分。
为了了解有关ImageList的更多信息,我重新阅读了您的文档:
图片列表说明:http://docwiki.embarcadero.com/Libraries/XE6/en/Vcl.Controls.TImageList
图片列表GetImageBitmap说明 http://docwiki.embarcadero.com/Libraries/XE6/en/Vcl.ImgList.TCustomImageList.GetImageBitmap