Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 4 of 4 total
Thread Loading queries in different threads
Mon, Mar 1 2010 11:58 AMPermanent Link

Robert Rowlands

Hello.

I'm looking at loading a small amount of data from a remote server (over a VPN) to get my application up and running ASAP.  I then thought I could load the remaining data in a different thread which, I assume, would run alongside the application and not slow it down.

Could someone please be kind enough to tell me how to do this.  I've no idea about threads and the info I have found only confuses things.

Thanks.

Rob.
Tue, Mar 2 2010 2:46 AMPermanent Link

Roy Lambert

NLH Associates

Team Elevate Team Elevate

Robert


There are a slew of helper classes and components out there (eg OmniThread, BMThread) but I've always found them to be more problematic than doing my own thing.

As long as you observe the golden rule of isolation simple single purpose threads aren't difficult.

My way of approaching is to test everything out in the foreground first (Its a lot easier to debug) and then move to a thread. I've attached an example of a thread I use to carry out background searches. Its invoked using this button click procedure

procedure TEMSearchForm.StartSearchesClick(Sender: TObject);
var
ems: TemSQLSearch;
begin
if not EMSearches_ID.IsNull then begin
//  StartSearches.Enabled := False;
 Update;
 if SpecAltered then begin
  EMSearches.Edit;
  EMSearches_SQG.AsString := emSQG.UserInputAsText;
  EMSearches_SQLWHERE.AsString := emSQG.FilterString;
  EMSearches.Post;
 end;
 PostMessage(MainHWND, ProgressReport, EMSearches_ID.AsInteger, 1);
 with emSearchParams do begin
  ReportBack := MainHWND;
  ConfigPath := dm.TfRSession.LocalConfigPath;
  Encryption := dm.TfRSession.LocalEncryptionPassword;
  Password := dm.TfRSession.LoginPassword;
  TempPath := dm.TfRSession.LocalTempTablesPath;
  Database := dm.DB.Database;
  SearchID := EMSearches_ID.AsInteger;
  UserID := HHCommons.UserID;
  MsgNo := ProgressReport;
 end;
 ems := TemSQLSearch.Create(emSearchParams);
end;
end;

and information is sent back to the main form via PostMessage with a handler

procedure TMainForm.TellEMSearchStatus(var Message: TMessage);
procedure RemoveSearchLine;
begin
 bgIsActive.Tag := bgIsActive.Tag - 1;
 if bgIsActive.Tag <= 0 then begin
  bgIsActive.Tag := 0;
  bgIsActive.Animated := False;
  bgIsActive.Visible := False;
 end;
end;
begin
lu.EMSearches.RefreshOrOpen;
if Message.LParam = 0 then begin
 if lu.EMSearches.FindKey([Message.WParam]) then begin
  RemoveSearchLine;
  nlhMessageDlg('The Email search ' + lu.EMSearches_Name.AsString + ' is finished with ' + lu.EMSearches_Hits.AsString + ' hits', mtInformation, [mbOK], 0);
 end else nlhMessageDlg('Current email search is completed.', mtInformation, [mbOK], 0);
end else if Message.LParam = 1 then begin
 if lu.EMSearches.FindKey([Message.WParam]) then begin
  bgIsActive.Tag := bgIsActive.Tag + 1;
  if not bgIsActive.Visible then begin
   bgIsActive.Animated := True;
   bgIsActive.Visible := True;
  end;
 end;
end else begin
 if lu.EMSearches.FindKey([Message.WParam]) then begin
  RemoveSearchLine;
  nlhMessageDlg('The Email search ' + lu.EMSearches_Name.AsString + ' failed with error code ' + IntToStr(Message.LParam), mtInformation, [mbOK], 0);
 end else nlhMessageDlg('Current email search failed with error ' + IntToStr(Message.LParam), mtInformation, [mbOK], 0);
end;
bgIsActive.Hint := 'Number of searches running: ' + IntToStr(bgIsActive.Tag);
end;

Since I have no interaction with any form's VCL components in the thread, and as you can see all the necessary ElevateDB bits (same applies to DBISAM) are created in the thread, I can ignore CriticalSections.

HTH

Roy Lambert [Team Elevate]





Attachments: emSearcher.pas
Tue, Mar 2 2010 4:20 AMPermanent Link

Robert Rowlands

Thank you Roy.

I tried to make a start last night but got an error.

That said, I was doing Begin/End Update of a visual component in the thread and I can see from your post that is a no no.

I'll go over your sample this evening.

Rob.
Tue, Mar 2 2010 6:35 AMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Robert,

<< Could someone please be kind enough to tell me how to do this.  I've no
idea about threads and the info I have found only confuses things. >>

Just use a TThread descendant (you can make a new unit from the File/New
options in the IDE), and override the Execute method.

In the Execute method, just use local variables for all TDBISAMSession,
TDBISAMDatabase, etc. components, and instantiate/free them within that
method (try..finally).

There's more info here on the DBISAM side of things:

http://www.elevatesoft.com/manual?action=viewtopic&id=dbisam4&product=d&version=7&topic=Multi_Threaded_Applications

--
Tim Young
Elevate Software
www.elevatesoft.com

Image