Solved

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

Posted on 2003-10-27
6
266 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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
I designed this idea while studying technology in the classroom.  This is a semester long project.  Students are asked to take photographs on a specific topic which they find meaningful, it can be a place or situation such as travel or homelessness.…
Need to grow your business through quality cloud solutions? With everything required to build a cloud platform and solution, you may feel like the distance between you and the cloud is quite long. Help is here. Spend some time learning about the Con…

932 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

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now