Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

How to make it possible for a user to interupt a search process?

Posted on 2003-10-27
6
Medium Priority
?
273 Views
Last Modified: 2010-04-05
Hi again :)

I have a small program written in Delphi 6.

The program search through small textfiles (5 - 10 kB) for textstrings the user specify and list the names of all files where the text match.
It search through a specified folder and it's subfolders. There are thousands of files so in the worse case , there can be more than thousen hits.
In that case, the user may want to interupt the search process and be more specific what he search for.

In the code I use a FindFirst  and FindNext to search through all files.

How do I make it possible for the user to interupt the process?
0
Comment
Question by:mieow
6 Comments
 
LVL 17

Accepted Solution

by:
Wim ten Brink earned 375 total points
ID: 9628762
Use a boolean variable, set it to False before you loop through the files list and set it to true when the user cancels the process. While you walk through the files, you also check if this variable is set to true. If so, quit looping...

Now, the problem is that while you're in this loop, the application won't respond to any messages. So also call Application.ProcessMessages in your loop or use multiple threads and walk through the files/folders in a separate loop. The latter option has a slightly higher performance but the first option is a lot easier.
0
 

Author Comment

by:mieow
ID: 9629284
I tried with a boolean but as you say, the application won't respond.
Can you give an example how to use Application.ProcessMessages?
0
 
LVL 6

Expert Comment

by:swift99
ID: 9631434
It is generally bad practice to call ProcessMessages from within your application - it can lead to unintended (and virtually untracable) event loops with nasty side effects.  I know Borland did this in some examples, but all that means is that hey get lazy sometimes too.

Another option is to use event driven programming techniques.  Kick the process off, and at the end of the process Postmessage with the message to perform the next step.  The event loop does all of the work, and your app never stops responding.

TMyForm = class (TForm)
...
protected
    procedure CancelProcess (message: TMessage); message WM_HandleCancel;
    procedure handlenextthing (message: TMessage); message WM_HandleNext;
...
end;

procedure CancelProcess (message: TMessage);
begin
    processing := false;
end;

procedure myForm.handlenextthing (message: TMessage);
begin
    if processing and (not myDataset.EOF) then
    begin
        myDataset.Next;
        ... Do Processing ...;
        PostMessage (handle, WM_HandleNext, 0, 0);
    end;
end;

This code has not been compiled or tested (obviously), and there are some places where I would go back and look at the online docs, such as the usage of the message directive.
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
LVL 17

Assisted Solution

by:geobul
geobul earned 375 total points
ID: 9632308
Hi,

Workshop_Alex is talking about something like (pressing Button1 starts the search and pressing Button2 stops it):

type
  TForm1 = class(TForm)
    Button1: TButton;
    RichEdit1: TRichEdit;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  stop: boolean;

implementation

{$R *.DFM}

function SearchInAFile(FileName: string; what: string): boolean;
begin
  result := true; // just for testing
  Sleep(200);
  // your code here
end;

procedure SearchFiles(DirStr: String; what: string; List: TStrings);
var
  DirInfo: TSearchRec;
  R: Integer;
begin
  R := FindFirst(DirStr + '*.*', faAnyfile, DirInfo);
  if R = 0 then begin
    repeat
      Application.ProcessMessages; // process messages inside the loop and check the boolean value
      if stop then exit;
      if (DirInfo.Name <> '.') and (DirInfo.Name <> '..') then begin
        if (DirInfo.Attr and faDirectory) <> 0 then begin
          SearchFiles(DirStr + DirInfo.Name + '\', what, List);
        end else begin
          if SearchInAFile(DirStr + DirInfo.Name, what) then
            List.Add(DirStr + DirInfo.Name);
        end;
      end;
      R := FindNext(DirInfo);
    until R <> 0;
    FindClose(DirInfo);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  stop := false;
  SearchFiles('C:\', 'geobul', RichEdit1.Lines);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  stop := true;
end;

end.

Regards, Geo
0
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 9634035
Yep, Geo gives the example that I had in mind. However, you have to be careful when you use ProcessMessages since it could lead to an endless loop of events and other problems. Theoretically, it would allow the user to press that buttun more than once,
Thus the use of a separate thread is a better solution. The separate thread could walk through the files and folders while your main thread just keeps processing everything. However, threads also have minor, annoying issues and need some careful planning.

The most useful trick however is simple: use a splash form with a single button and display this form as a modal form. Use ProcessMessages to keep the splashform responsive and once the user presses the button on the splashform, the user is able to create other events in your application too. (The splashform just blocks the other events.) Of course, when you're done walking through all files and folders you could close the splashform too. Using a small splashform this way would be the easiest way to get around the problems that swift99 mentioned...
0
 

Author Comment

by:mieow
ID: 9635141
Thanks both of you, Workshop_Alex and Geo.
The solution with Application.ProcessMessages worked like a charm.
I'll have to give both of you credits for this.
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
In a question here at Experts Exchange (https://www.experts-exchange.com/questions/29062564/Adobe-acrobat-reader-DC.html), a member asked how to create a signature in Adobe Acrobat Reader DC (the free Reader product, not the paid, full Acrobat produ…
Screencast - Getting to Know the Pipeline

926 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question