簡體   English   中英

如何將線程結果保存到數據庫中

[英]How can I save the thread results in a Database

正在處理項目,我想將下載的圖像保存在Blob字段中。 我成功使用idHTTP,但UI凍結。

我創建了一個使用ImageLoader方法從URL下載圖像的過程( Image Loader頁面 )。 圖像一切正常,但是我無法將它們保存在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;

如果我只想顯示圖像,則代碼可以完美工作。 如何使用流保存它們?

問題
問題是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速度較慢,因此最好將其拉出循環(由於FieldByName的速度較慢,這可能LoadImageNow )。

請參閱: http : //docwiki.embarcadero.com/Libraries/XE5/en/Data.DB.TBlobField.Assign
並且: http : //docwiki.embarcadero.com/CodeExamples/XE3/en/HTTP_Get_%28Delphi%29

其他選擇
將事件添加到線程,每當圖像完成加載時,您就可以將其掛接到其中。
然后,您可以在事件處理程序中顯示圖像並將其放入數據庫中。
實際上,異步加載器可能已經為此提供了一個選項,但是我不知道該代碼庫是否足以回答該問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM