Solved

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

Posted on 2003-10-27
6
265 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
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
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

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

743 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

13 Experts available now in Live!

Get 1:1 Help Now