如何将线程结果保存在数据库中

时间:2014-04-23 16:36:14

标签: android database multithreading delphi delphi-xe5

处理项目,我想保存我在blob字段中下载的图像。我成功使用idHTTP但UI冻结。

我创建了一个使用ImageLoader方法(Image Loader page)从URL下载图像的过程。图像一切正常,但我无法将它们保存在DB中的特定字段中。

我该怎么做?

这是我的代码:

procedure TForm1.LoadImages;
var
  i: integer;
  IMLO: TImageLoader;
  IM: TImage;
  Stream: TMemoryStream;
  imgAddress: string;

begin
  Table1.First;
   for i := 0 to Table1.RecordCount-1 do
     begin
       imgAddress := Table1.FieldByName('URL').AsString;
       Stream := TMemoryStream.Create;
       IM:= TImage.Create(self);
       IM.Name := 'IM'+inttostr(i);
       IM.Parent := HorzScrollBox1;
       IM.Position.X := i * 320;
       IM.Align:= TAlignLayout.alLeft;
       IM.Width := 300;
       IMLO.LoadImage(IM, imgAddress);
 {      Table1.Edit;
       TBlobField(Table1.FieldByName('image')).LoadFromStream(Stream);
       Table1.Post; 
       Stream.Free;  }
       Table1.Next;
     end;
end;

如果我只想显示图像,代码可以正常工作。如何使用流来保存它们?

1 个答案:

答案 0 :(得分:1)

<强>问题
问题是TImageLoader.LoadImage异步加载来自网络的数据 因此,当您重新加载数据时,数据尚未可用。

简单解决方案
为了阻止TImageLoader执行此操作,您可以为其添加一个额外的方法并调用该方法 另一个问题是您使用Stream数据加载Blob,但是您从不加载任何内容。
幸运的是,你不需要这条小溪。

function TImageLoader.LoadImageNow(const AImage: TImage; const AImageURL: string): boolean;
const
  success = true;
  failure = false;
var
  MS : TMemoryStream;
  Image: TImage;
begin
  Result:= success;
  MS := TMemoryStream.Create;
  Image:= TImage.Create;
  try
    IdHTTP1.get(AImageURL,MS);
    Ms.Seek(0,soFromBeginning);       
    Image.LoadFromStream(MS);
    AImage.Picture.Assign(Image);   
  except
    Result:= failure;
  end;
  FreeAndNil(Image);
  FreeAndNil(MS);
end;

现在加载程序只会在加载图像时返回。 这也解释了为什么在释放IM时获得例外 您正在释放IM,但加载程序仍在后台使用它 这就是使用多线程应用程序的问题,您需要跟踪其他线程正在做什么。

循环的代码现在看起来像这样:

procedure TForm1.LoadImages;
var
  i: integer;
  IMLO: TImageLoader;
  IM: TImage;
  imgAddress: string;
  FieldImage: TGraphicField;
  FieldUrl: TField;
begin
  FieldImage:= TGraphicField(Table1.FieldByName('image'));
  FieldUrl:= Table1.FieldByName('URL');

  Table1.First;
  for i := 0 to Table1.RecordCount-1 do try
    imgAddress := FieldUrl.AsString;
    IM:= TImage.Create(self);
    IM.Name := 'IM'+inttostr(i);
    IM.Parent := HorzScrollBox1;
    IM.Position.X := i * 320;
    IM.Align:= TAlignLayout.alLeft;
    IM.Width := 300;
    if IMLO.LoadImageNow(IM, imgAddress) then begin
      Table1.Edit;
      FieldImage.Assign(IM.Picture);
      Table1.Post; 
    end; {if}
  finally  
    IM.Free;
    Stream.Free;  
    Table1.Next;
  end; {for .. try}
end;

因为FieldByName很慢,所以最好将它从循环中拉出来(由于LoadImageNow的速度慢,这可能无关紧要。)

请参阅:http://docwiki.embarcadero.com/Libraries/XE5/en/Data.DB.TBlobField.Assign
并且:http://docwiki.embarcadero.com/CodeExamples/XE3/en/HTTP_Get_%28Delphi%29

其他选项
在每次图像完成加载时可以挂钩的线程中添加一个事件 在事件处理程序中,您可以显示图像并将其放入数据库中 事实上,异步加载器可能已经有了一个选项,但我不知道该代码库足以回答这个问题。