首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >线程中的图像检索器

线程中的图像检索器
EN

Stack Overflow用户
提问于 2009-10-07 21:27:45
回答 2查看 406关注 0票数 2

我正在尝试制作一个使用列表的图像检索器。

例如,该列表包含类型为(TItem)的项。TItem有一些属性,比如标题、图片和imageURL。

列表中有一个线程,它扫描所有项目,并尝试使用每个项目的imageURL检索每个项目的图像。

检索每一项图像的线程的工作方式如下:

代码语言:javascript
复制
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;

不幸的是,它在一种情况下不起作用:当列表被清除时,线程正在检索项目的图像。

(所有读取和写入的项都受互斥保护)。

我该怎么做?

谢谢:)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2009-10-08 06:14:09

基本问题是您的代码不能使用互斥来保护循环本身。正如您可能意识到的那样,这将产生一个巨大的互斥,从而显著降低系统的运行速度。

这是一个很好的解决方案:

for循环替换为查找下一个URL的while-loop

  • Create代码,并且互斥保护该代码

  • 使图像检索使用与列表无关的变量,因此它不需要互斥保护通过使用URL找到正确的索引来检索到的图像。此查找和存储必须受互斥锁保护。

如下所示:

代码语言:javascript
复制
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语句等。

票数 3
EN

Stack Overflow用户

发布于 2009-10-07 21:48:50

有很多方法可以解决这个问题,这里有两个例子:

  • 不使用对象列表,而是使用TInterfaceList或通用接口列表。从item类的公共方法创建一个接口。线程将维护一个接口引用,保持引用计数大于零,因此实现该接口的对象实例不会被删除。因此,访问项目将是安全的。
  • 不直接从线程访问项目,而是仅为线程提供一个不透明的项目句柄。最初,线程将使用该句柄来请求获取图像所需的数据,并且由于它将锁定列表,因此访问是安全的。当检索到图像时,线程将再次使用该句柄将图像设置为锁定代码段中的项。如果项目不再有效,句柄将不会解析为项目,检索到的图像将被简单地删除。您只需确保句柄不会被重用,例如,列表索引或项的地址都不是好主意。将为每个项目递增的整数OTOH将工作得很好。

第二种方式的简化代码:

代码语言:javascript
复制
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()调用基本上是轮询。开销不大,但风格仍然不好。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1534310

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档