我正在尝试制作一个使用列表的图像检索器。
例如,该列表包含类型为(TItem)的项。TItem有一些属性,比如标题、图片和imageURL。
列表中有一个线程,它扫描所有项目,并尝试使用每个项目的imageURL检索每个项目的图像。
检索每一项图像的线程的工作方式如下:
while not terminated do
begin
for i := 0 to List.count-1 do
begin
item := List.Items[i];
//Note : it can takes a few sec to retrieve the image from the imageURL. This method
//retrieve the image from the item.imageURL and then assign it to item.image
RetrieveImage(item.imageURL, item.Image);
end;
sleep(100);
end;不幸的是,它在一种情况下不起作用:当列表被清除时,线程正在检索项目的图像。
(所有读取和写入的项都受互斥保护)。
我该怎么做?
谢谢:)
发布于 2009-10-08 06:14:09
基本问题是您的代码不能使用互斥来保护循环本身。正如您可能意识到的那样,这将产生一个巨大的互斥,从而显著降低系统的运行速度。
这是一个很好的解决方案:
for循环替换为查找下一个URL的while-loop
如下所示:
while not terminated do
begin
currenturl:='';
while true do begin
Mutex begin
currenturl:=FindNextUrl(currentUrl);
Mutex end
if currenturl='' then break; // No more URLs to be found
RetrieveImage(currenturl,image);
Mutex begin
index:=FindUrlIndex(currenturl)
List[index].image:=image;
Mutex end
end;
sleep(100);
end;自己添加必要的互斥代码、try语句等。
发布于 2009-10-07 21:48:50
有很多方法可以解决这个问题,这里有两个例子:
TInterfaceList或通用接口列表。从item类的公共方法创建一个接口。线程将维护一个接口引用,保持引用计数大于零,因此实现该接口的对象实例不会被删除。因此,访问项目将是安全的。第二种方式的简化代码:
var
Img: TImage;
ImgHandle: TImageFromURLHandle;
...
Img := TImage.Create;
try
while not Terminated do
begin
// GetNextImageURL() is thread-safe
while List.GetNextImageURL(ImgHandle, ImgURL) do begin
RetrieveImage(ImgURL, Img);
// SetImage() is thread-safe and will do nothing if the image item
// is no longer in the list (invalid handle)
List.SetImage(ImgHandle, Img);
end;
Sleep(100);
end;
finally
Img.Free;
end;您甚至可以使用图像URL本身作为句柄。
请注意,如果列表为空,则更好的方法是阻塞线程,您的Sleep()调用基本上是轮询。开销不大,但风格仍然不好。
https://stackoverflow.com/questions/1534310
复制相似问题