Allowing two separate Delphi applications/processes to communicate

Hello experts.

I have a very sorted large string list (up to 30,000 items) that I need to (a) read from disk and then (b) search and return an item from the list.  I am thinking of loading this to a TStringList.  However, the search and item return may have to be repeated many times in a given session, and so I would like to avoid repeating the bottleneck of reading the large list into memory each time a search is requested.

So is there a means to (1) Load the string list into memory one time at the beginning of a session, and (2) have a separate process search the string list (already loaded in memory) and return the item?  It sounds like a DLL to me, but I have never used DLLs and so would need help...or a better idea.

I am posting the question with higher points in the hopes of some basic code examples.

Thanks.

Roger
Roger_HanggiAsked:
Who is Participating?
 
TheRealLokiConnect With a Mentor Senior DeveloperCommented:
This is how I'd do what you want, by using a thread.
The thread is the only thing dealing with the list, so it loads it, and searches it when you ask it to.
It returns the 1st string it finds containing your search word

You will need a TButton, a TMemo, a Button1Click, and a FormClose event

unit unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
    TOnStringListFoundWordEvent = procedure(Sender: TObject; const SearchString: string; FoundString: string; FoundIndex: integer) of object;
type
    TOnStringListNotFoundWordEvent = procedure(Sender: TObject; const SearchString: string) of object;

type TStringListLoadAndSearchThread = class(TThread)
    private
        SL: TStringList;
        foundindex: integer;
        foundcompletestring: string;
        OnStringListFoundWordEvent: TOnStringListFoundWordEvent;
        OnStringListNotFoundWordEvent: TOnStringListNotFoundWordEvent;
    public
        SearchString: string;
        constructor Create(Listfilename: string; OnFoundEvent_: TOnStringListFoundWordEvent; OnNotFoundEvent_: TOnStringListNotFoundWordEvent);
        procedure Execute; override;
// synchronized events
        procedure FoundString;
        procedure NotFoundString;
    end;

type
  TForm2 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
    procedure OnStringListFoundWord(Sender: TObject; const SearchString: string; FoundString: string; FoundIndex: integer);
    procedure OnStringListNotFoundWord(Sender: TObject; const SearchString: string);
  public
    { Public declarations }
    workerthread: TStringListLoadAndSearchThread;
  end;

var
  Form2: TForm2;

implementation

{$R *.DFM}

{ TStringListLoadAndSearch }

constructor TStringListLoadAndSearchThread.Create(Listfilename: string;
  OnFoundEvent_: TOnStringListFoundWordEvent;
  OnNotFoundEvent_: TOnStringListNotFoundWordEvent);
    begin
        inherited Create(true);
        OnStringListFoundWordEvent := OnFoundEvent_;
        OnStringListNotFoundWordEvent := OnNotFoundEvent_;
        SL := TStringList.Create;
        if FileExists(ListFilename) then
          SL.LoadFromFile(ListFIlename);
    end;

procedure TStringListLoadAndSearchThread.Execute;
    var
        i: integer;
    begin
        while (not terminated) and (SearchString <> '') do
        begin
            foundindex := -1;
            foundcompletestring := '';
            i := 0;
            while ( (not Terminated) and (foundindex = -1) and (i < SL.Count) ) do
            begin
                if pos(SearchString, SL[i]) > 0 then
                begin
                    foundindex := i;
                    foundcompletestring := SL[i];
                end
                else inc(i);
            end;
            if (not Terminated) and (foundindex <> -1) then
            begin
                synchronize(FoundString);
                Suspended := True;
            end
            else if (not Terminated) and (foundindex = -1) then
            begin
                synchronize(NotFoundString);
                Suspended := True;
            end;
        end;

    end;

procedure TStringListLoadAndSearchThread.FoundString;
    begin
        if assigned(OnStringListFoundWordEvent) then
          OnStringListFoundWordEvent(self, SearchString, FoundCompleteString, FoundIndex);
    end;

procedure TStringListLoadAndSearchThread.NotFoundString;
    begin
        if assigned(OnStringListNotFoundWordEvent) then
          OnStringListNotFoundWordEvent(self, SearchString);
    end;

procedure TForm2.Button1Click(Sender: TObject);
    begin
        if not assigned(workerthread) then
          workerthread := TStringListLoadAndSearchThread.Create('strings.txt', OnStringListFoundWord, OnStringListNotFoundWord);
        if workerthread.Suspended then
        begin
            workerthread.SearchString := edit1.Text;
            workerthread.Resume;
        end
        else
          showmessage('I am still searching another word');
    end;

procedure TForm2.OnStringListFoundWord(Sender: TObject; const SearchString: string; FoundString: string; FoundIndex: integer);
    begin
        Memo1.Lines.Add('Found "' + SearchString + '" in string "' + FoundString + '" at position ' + IntToStr(FoundIndex));
    end;

procedure TForm2.OnStringListNotFoundWord(Sender: TObject; const SearchString: string);
    begin
        Memo1.Lines.Add('Did not find "' + SearchString + '"');
    end;

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
    if assigned(workerthread) then
    begin
        workerthread.terminate;
        if workerthread.suspended then workerthread.resume;
        workerthread.waitfor;
    end;
end;

end.

0
 
AshusCZCommented:
You might try to use threads. No need for separate applications.

Here's a simple example of how to use threads:

unit ThrWrite;

interface

uses
  Classes, ComCtrls, forms;

type
  TThrWrite = class(TThread)
  private
    FProgressBar : TProgressBar;
  protected
    procedure Execute; override;
  public
    constructor Create(var i:integer);
    property ProgressBar: TProgressBar write FProgressBar;
    procedure CCount;
  end;

var o: integer;

implementation

{ TThrWrite }

constructor TThrWrite.Create(var i:integer);
begin
inherited Create(true);
o:=i;
end;


procedure TThrWrite.Execute;
begin
Fuck;
end;


procedure TThrWrite.CCount;
begin
repeat
Inc(o);
FProgressBar.position:=o;
until o=50000;
end;

end.


/////////////////////////////////


unit ThrWrite;

interface

uses
  Classes, ComCtrls, forms;

type
  TThrWrite = class(TThread)
  private
    FProgressBar : TProgressBar;
  protected
    procedure Execute; override;
  public
    constructor Create(var i:integer);
    property ProgressBar: TProgressBar write FProgressBar;
    procedure CCount;
  end;

var o: integer;

implementation

{ TThrWrite }

constructor TThrWrite.Create(var i:integer);
begin
inherited Create(true);
o:=i;
end;


procedure TThrWrite.Execute;
begin
CCount;
end;


procedure TThrWrite.CCount;
begin
repeat
Inc(o);
FProgressBar.position:=o;
until o=50000;
end;

end.
0
 
AshusCZCommented:
oops..

procedure TThrWrite.Execute;
begin
Fuck;    ------->      CCount;
end;

sorry for that, it was given to me from some rude guy and i missed one occurence while replacing..
0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
atul_parmarConnect With a Mentor Commented:
Using a DLL for string handling will require you to deploy the BorlandMM along with your application. If that's not a problem then you can go with a DLL.

Another thing you can do is to load the list when your session starts and when you need to find the item, just use the previously loaded list.
0
 
atul_parmarCommented:
var
  MyStrings : TStringList;

function FindString(StringToFind : String) : Boolean;
var
  Idx : Integer;
begin
  If Not Assigned(MyStrings) then // load the list
  begin
    MyStrings := TStringList.Create;
    MyStrings.LoadFromFile('FileName');
    MyStrings.Sort;
  end;
  Result := MyStrings.Find(StringToFind, Idx);
end;
0
 
TheRealLokiSenior DeveloperCommented:
if the TStringlist is sorted, and you are searching for a complete string, then you can just do
i := SL.indexof('string'); which will be very fast and not require a thread
0
 
Roger_HanggiAuthor Commented:
Thanks for your help.  I wanted to split points between Atul Parmar for clarifying the issues of using a DLL and TheRealLoki for a complete code example of using threads.
0
All Courses

From novice to tech pro — start learning today.