Solved

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

Posted on 2003-10-27
6
269 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 125 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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 17

Assisted Solution

by:geobul
geobul earned 125 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

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Working with hours 3 72
Reconfigure Delphi Install? 2 64
MS Access from Delphi 31 78
How to save the image in the .cds File ClientDataSet? 1 28
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…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…
How to Install VMware Tools in Red Hat Enterprise Linux 6.4 (RHEL 6.4) Step-by-Step Tutorial

685 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