views:

205

answers:

2

Hi. Could you help me please. I'm writing a component (something like TListView), In my component I perform 3 procedures one by one:

procedure findFiles(Path:String); // using FindFirst, FindNext
procedure ArrangeItems; // assigns Item Position
procedure SetIcons;    // Loads Images, resizes, adds to ImageList

I can not understand how to make my component use Threads to perform all these procedures, at least the first one (findFiles). I've tried different ways but nothing comes out.

Here is a scetch of what I have (just a basic example).

 type
  TSearchThread = class(TThread)
  private
    SIView: TSIView;
  protected
    procedure Execute; override;
    procedure DoSearch;
  public
    constructor Create(fSIView: TSIView);
  end;



 constructor TSearchThread.Create(fSIView: TSIView);
 begin
  SIView := fSIView;
  FreeOnTerminate := True;
  inherited Create(False);
  Priority := tpLower;
 end;

 procedure TSearchThread.Execute;
 begin
  inherited;
  Synchronize(DoSearch);
 end; 

 first I tried to perform 
   SIView.findFiles('C:\');
   ArrangeItems;

and only then execute the thread to set appropriate icons (SetIcons):

 procedure TSearchThread.DoSearch;
 begin
  SetIcons;
 end;

It worked but with bugs: sometimes my component created icons not for all items, sometimes some items had an icon fully filled with black colour and sometimes I had no icons at all;

then I decided to perform all the 3 procedures in the thread:

 procedure TSearchThread.DoSearch;
 begin
  SIView.findFiles('C:\');
  ArrangeItems;
  SetIcons;
 end; 

As a result I had the same bugs with creating Icons and instead of searching in a specified folder it searched in the folder where my application was.

For you to understand me more, I am trying to write a file manager with multiple tabs, so as far as I understand, I need to use Threads so that application will not freeze when dealing with multiple tabs.

Could you help me please to understand how to arrange my code?!!!! Maybe you could give an example because there in not many documentation concerning Threading.


Hi again.
I've tried both AsyncCalls and OmniThreadLibrary. They both had an example of "Background" file search. First I found AsyncCalls more suitable for my application as it really did its job well. I used AsyncCalls to perform my three procedures and it was what I had been looking for. I also tried calling my procedures using OmniThreadLibrary but it seemed like they were not performed in a thread. That's why I prefered AsyncCalls, but I have a question, HOW TO STOP IAsyncCall when it is running? I mean, for example, as I've mentioned before my application is multitabbed and if a user opens 3 tabs and on each tab executes file searching, then how can I stop file searching on the second tab?

To make it more clear for you to understand what I want to do, here is a sketch:

A form has 3 TMemo, 3 TButton

var 
 a1, a2, a3: IAsyncCall;


procedure TForm1.Search(Path:String; MEMO:TMemo);
begin
 /////// Finds files and adds to MEMO 
end;

All the three buttons do the same, except they point to differen TMemo (Memo1, Memo2, Memo3);

procedure TForm1.Button1Click(Sender: TObject);

 procedure DoSearch;
 begin
  Search('C:\', Memo1);     
 end;

begin
  a1 := LocalAsyncCall(@DoSearch);

  while AsyncMultiSync([a1], True, 0) = WAIT_TIMEOUT do
      Application.ProcessMessages;
end;

So, if I click all the three buttons, I'll have 3 IAsyncCall running. How to stop any of them while it is still running?

+4  A: 

i think wich your best option is use the AsyncCalls library, wich is very easy to use, and in the webpage includes a demo very similar to your example.

RRUZ
+3  A: 

With the code like this

 procedure TSearchThread.Execute;
 begin
  inherited;
  Synchronize(DoSearch);
 end; 

you don't use a worker thread at all - all work is done in the main thread via Synchronize call. That is an example how one should not use threads. In short, your Execute code may look like this:

 procedure TSearchThread.Execute;
 begin
   if FindFirst(..) then begin
     repeat
       Queue(..); // inform the main thread about the item is found
     until not FindNext(..)
     FindClose;
   end;
   Queue(..); // inform the main thread that the work is completed
              //   and we are about to terminate
 end; 
Serg