Clément
Clément

Reputation: 91

Delphi - OTL - Communicating between ThreadPool and Worker thread

I'm using XE8 and I'm trying to built an example of my real world application.

I need to communicate between the main "service thread" and the OTL thread pool. The examples are all set with forms and Monitors. I don't need those, but I can't figure out a way to write a clean code. So far this is what I did:

TProcessWorker = Class( TOmniWorker )
strict private
  FTaskID : int64;
  FIndex : Integer;
  FFolder : String;
protected
  function Initialize: Boolean; override;
public
  procedure WriteTask( var msg : TMessage); message _AM_WriteTask;
End;

{ TProcessWorker }

function TProcessWorker.Initialize: Boolean;
begin
  FTaskID := Task.UniqueID;
  FIndex := 0;
  result := True;
  FFolder := Format('%s/%d', [Task.Param['Folder'].AsString, FTaskID]);
  ForceDirectories(FFolder);
end;

Implemented as:

procedure TProcessWorker.WriteTask(var msg: TMessage);
var
  ps : PString;
  L : TStringStream;
begin
   Ps:= PString(msg.LParam);
   L := TStringStream.Create( ps^ );
   try
     L.SaveToFile( format('%s\%d.txt',[FFolder, fIndex]) );
   finally
     l.Free;
     inc(FIndex);
   end;
end;

In the main thread, to create the pool, I'm calling:

FThreadPool := CreateThreadPool('Thread pool test');

and

var
  lFolder : String;
  Process : IOmniWorker;
begin
   lFOlder := ExtractFilePath(ParamStr(0));
   Process := TProcessWorker.Create;
   CreateTask( Process, 'Task test').Unobserved.SetParameter('Folder',lFolder).Schedule(FThreadPool);

I don't know how to call correctly my worker thread. In my real application, several thread will be triggered and I need to be sure I using correctly the threadpool.

1) By calling CreateTask as I am, how am I making a correct use of threadpool? It's seems odd to me to call CreateTask for every Process I need.

2) The worker thread is never triggered. How should I make my Worker thread work! :)

Regards, Clément

Upvotes: 3

Views: 1120

Answers (2)

gabr
gabr

Reputation: 26850

OmniThreadLibrary test 08_RegisterComm shows how to communicate directly between two threads.

Basically, you have to create an instance of IOmniTwoWayChannel and register its endpoint in the worker's Initialize method with Task.RegisterComm(<channel>).

You can then send messages in a 'normal' way with <channel>.Send(<message>, <data>) and they will be dispatched to other task's message method if you decorate it in a Delphi way:

procedure MessageHandler(var msg: TOmniMessage); message <message>;

Upvotes: 1

Arioch &#39;The
Arioch &#39;The

Reputation: 16125

check http://otl.17slon.com/book/doku.php?id=book:howto:connectionpool

my feeling is that OTL is based upon data containers, not threads.

so I think you need to make a queue of task requests that your "main thread" would inject tasks into.

the idea of pools is that they manage themselves! you should not communicate with a specific worker thread, you should just sent work requests into it, and then let the pool spawn/kill worker threads as it sees fit.

if you need feedback from every specific thread, I'd rather include TForm.Handle or maybe the TOmniMonitor pointer into the task request record, and make the worker thread to call back and communicate with the form, no the from with the thread

Upvotes: 0

Related Questions