Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 5 of 5 total
Thread threading and data-aware controls
Fri, Mar 30 2007 2:48 PMPermanent Link

Jason Lee
Hi All,

I'm rearranging some of my threading stuff in an app.
How do I run a query that takes a few minutes in a background thread and
then display its results in a data-aware grid when it's done.

I'd prefer the thread to terminate when finished, but this is not
absolutely required. Can I create a memory table in a thread that can be
been by my main VCL thread?

Using D7, DBISAM V4 C/S

TIA,

Jason Lee
Sat, Mar 31 2007 5:28 AMPermanent Link

Roy Lambert

NLH Associates

Team Elevate Team Elevate

Jason


Its not difficult. I'm stuck some code below to give you a bit of an idea but essentially, as long as you only run the query from the form

1. Declare the thread class before your form class
2. Add a private variable of the thread class type to the form
3. Drop a TDBISAMQuery component on the form
4. Create a procedure as part of the class declaration to handle the return message
5. Run the query ...    thrdFinder := TQThread.Create(Finder, Self.Handle);


Roy Lambert




//Thread class declaration - very simple
type
TQThread = class(TThread)
private
 FSearcher: TDBISAMQuery;
 FRespondTo: HWND;
protected
 procedure Execute; override;
public
 constructor Create(SearchQry: TDBISAMQuery; RespondTo: HWND);
end;

constructor TQThread.Create(SearchQry: TDBISAMQuery; RespondTo: HWND);
begin
inherited Create(True); // Create thread in a suspendend state so we can prepare vars
FSearcher := SearchQry; //Set up local query var to be executed.
FRespondTo := RespondTo;
FreeOnTerminate := True; //Free thread when finished executing
Resume;
end;

procedure TQThread.Execute;
begin
FSearcher.ExecSQL; //Perform the query
PostMessage(FRespondTo, srchDone, 0, 0);
end;

procedure TMNSearchForm.SearchComplete(var Message: TMessage);
begin
ResultsTab.TabVisible := True;
SearchRunning := False;
Progress.Progress := 0;
Progress.Visible := False;
ResultsTab.TabVisible := True;
ResultsTab.Caption := 'Results: ' + IntToStr(Finder.RecordCount) + ' items found';
SpeedButton1.Visible := True;
dsFinder.DataSet := Finder;
PageControl1.ActivePage := ResultsTab;
Panel1.Visible := False;
if Finder.RecordCount > 0
 then FinderAfterScroll(Finder)
end;
Sat, Mar 31 2007 12:19 PMPermanent Link

Jason Lee
Roy,

Great, thank you and I'll give it a try, but this begs the question:
doesn't this break the rules for DBISAM and multithreading? (i.e.
separate session, database, tables, queries, etc.)

Thanks again,

Jason Lee

Roy Lambert wrote:
> Jason
>
>
> Its not difficult. I'm stuck some code below to give you a bit of an idea but essentially, as long as you only run the query from the form
>
> 1. Declare the thread class before your form class
> 2. Add a private variable of the thread class type to the form
> 3. Drop a TDBISAMQuery component on the form
> 4. Create a procedure as part of the class declaration to handle the return message
> 5. Run the query ...    thrdFinder := TQThread.Create(Finder, Self.Handle);
>
>
> Roy Lambert
>
>
>
>
> //Thread class declaration - very simple
> type
> TQThread = class(TThread)
> private
>   FSearcher: TDBISAMQuery;
>   FRespondTo: HWND;
> protected
>   procedure Execute; override;
> public
>   constructor Create(SearchQry: TDBISAMQuery; RespondTo: HWND);
> end;
>
> constructor TQThread.Create(SearchQry: TDBISAMQuery; RespondTo: HWND);
> begin
> inherited Create(True); // Create thread in a suspendend state so we can prepare vars
> FSearcher := SearchQry; //Set up local query var to be executed.
> FRespondTo := RespondTo;
> FreeOnTerminate := True; //Free thread when finished executing
> Resume;
> end;
>
> procedure TQThread.Execute;
> begin
> FSearcher.ExecSQL; //Perform the query
> PostMessage(FRespondTo, srchDone, 0, 0);
> end;
>
> procedure TMNSearchForm.SearchComplete(var Message: TMessage);
> begin
> ResultsTab.TabVisible := True;
> SearchRunning := False;
> Progress.Progress := 0;
> Progress.Visible := False;
> ResultsTab.TabVisible := True;
> ResultsTab.Caption := 'Results: ' + IntToStr(Finder.RecordCount) + ' items found';
> SpeedButton1.Visible := True;
> dsFinder.DataSet := Finder;
> PageControl1.ActivePage := ResultsTab;
> Panel1.Visible := False;
> if Finder.RecordCount > 0
>   then FinderAfterScroll(Finder)
> end;
Sun, Apr 1 2007 5:17 AMPermanent Link

Roy Lambert

NLH Associates

Team Elevate Team Elevate

Jason


The reason for creating separate sessions, tables, queries etc is so that DBISAM / Delphi knows that its separate and will apply locking etc as necessary and so that memory doesn't get overwritten. If NOTHING else uses the query then you're safe.

In my app, and condoned by The Great Tim I also have an OnProgress event attached to the query updating a progress bar.

Roy Lambert
Tue, Apr 3 2007 9:21 AMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Jason,

<< Great, thank you and I'll give it a try, but this begs the question:
doesn't this break the rules for DBISAM and multithreading? (i.e. separate
session, database, tables, queries, etc.) >>

You can break the DBISAM threading rules if you know what you're doing and
can guarantee that only one thread will be accessing a particular DBISAM
component at the same time.

--
Tim Young
Elevate Software
www.elevatesoft.com

Image