PatV
-
Content Count
39 -
Joined
-
Last visited
Posts posted by PatV
-
-
Thanks again Primož,
So glad you are around.
Patrick
-
Delphi 10.3
Omnithead 3.07.5
Hi All,
I'm just a little lost, I would like to pass parameters to the data factory, I know I can pass function like this
TOTPThreadDataFactoryFunction = function: IInterface;
TOTPThreadDataFactoryMethod = function: IInterface of object;and my function is like
{-------------------------------------------------------------------------------------------------}
function TFConfig.CreateThreadPool(aHandle : THandle ; aConfig : rConnectionConfig ; aValue: string) : iOmniThreadPool;
var
iOmniValue : TOmniValue;
begin
iOmniValue := TOmniValue.FromRecord<rConnectionConfig>(aconfig);result := otlThreadPool.CreateThreadPool(aValue);
result.MaxExecuting := result.NumCores;result.SetThreadDataFactory
(
(function (aHandle : THandle ; aConfig : TOmniValue) : IInterface
begin
result:=Function : IInterface
begin
result:= ??
end;
end
)(aHandle,iOmniValue )
);end;
{-------------------------------------------------------------------------------------------------}
rConnectionConfig is a record containing info on to be able to connect to the datamodule
RConnectionConfig = record
User : string;
Password : string;
Database : string;
Protocol : string;
Port : integer;
HostName : string;
LibraryLocation : string;
ModuleName : string;
end;Could someone help me with this
Thanks
Patrick
-
Thanks again Primoz for your fast answer, I'll go with task.Comm.Send
Regards
Patrick
-
Delphi 10.3
Omnithead 3.07.5
Hi all,
I'm testing and playing with the sample 24_ConnectionPool, so in the main form I've added
procedure TfrmConnectionPoolDemo.btnScheduleClick(Sender: TObject);
var
i : integer;
Params : TParameters;begin
WithParamsReset(Params);
WithParam(Params,cDteFrom,'2019/01/01',dtString);
WithParam(Params,cDteTo ,'2019/09/01',dtString);
for i:=0 to 99 do // for testing purpose launch 100 task
begin
Log(Format('Creating task %d',));
CreateTask(Worker,format('%0.2d',))
.MonitorWith(OTLMonitor)
.SetParameter('Params',TOmniValue.FromArray<rParameter>(Params))
.SetParameter('ProcName','prc_ProcedureToCall')
.Schedule(FConnectionPool);
end;
end;now my question is ;
how can I retreive the result of the data connection in an object and send it from task Worker to the main thread ?
I was thinking about msg.msgData from IOmniMessage and retreive it through OTLMonitor or insert a TOmniTaskInvokeFunction into my Worker task
What is the best way ?
Thanks
Patrick
-
Thanks a lot Primož, it helps me a lot.
And thanks for sharing Omnithread
Patrick
-
Delphi 10.3
Omnithead 3.07.5
Hi All
here is a definition of an array of ..
TpDataType = (dtNone, dtInteger, dtDateTime, dtString, dtBlob);
rParameter = record
Field : string;
Value : Variant;
AsValue : TpDataType;
end;TParameters = array of rParameter;
I would like to pass it to a worker as parameter, so
CreateTask(Worker)
.MonitorWith(OTLMonitor)
.SetParameter('Params',TOmniValue.Create([Params]);I've tried also
.SetParameter('Params',TOmniValue.FromArray<TParameters>(Params))
and convert it again like
function TConnectionPoolData.WithParameters(const aValue : TOmniValue) : IConnectionPoolData;
begin
FParams := aValue.CastTo<TParameters>;Result:=Self;
end;
But it's not working as expected, as I'm getting bunch of data
Do I need to use a class instead ?
Thanks
Patrick
-
Thanks John !
Will take my time to read it.
-
Thanks a lot Peter,
I will check the code the follow your advice.
-
Found the prob.... it's too quick, I need to introduce a delay in my loop and everything is working
now if you have any suggestions, you're welcome
Hi All,
I'm using Delphi 10.3
As testing, I've a main form
when I click on MyForm Create Thread Button, I launch the code bellow ;
I create a form TForm.Create(Self) and I include a frame in it TFrm.Create(Self)
GetTGUIDString simply convert number from TGIUID.NewGuid.ToString to letter, and remove special char to get a random name.
In My Frame,
I have defined a Thread ;
TThDb = class(TThread)
private
FOwner : TComponent;
FDM : TFDb; // is a datamodule who will be created within the tread
FEvent : TEvent;
FError : TFError;
FRet : TFRet;
FAgs : string;
FWhenDone : PrcDone;
procedure InitializeDatabase;
procedure ConnectToDatabase;
Procedure WorkOnData;
function LoadData : TThDb;
procedure Execute; override;
public
constructor Create(bSuspended : boolean);
destructor Destroy; override;
property Event : TEvent read FEvent write FEvent;
function WhenDone(aValue : PrcDone) : TThDb;
function WithAgencies(aValue : string) : TThDb;
function WithOwner(aValue : TComponent) : TThDb;
procedure Start; // initialise the connection to the database the first time
procedure ReStart; // update the variable in the query/procedure
end;{------------------------------------------------------------------------------}
procedure TTHDB.InitializeDatabase;
begin
CoInitialize(Nil);
FDM := TFDb.Create(nil);
FDM.Connection.ReadOnly:=True;
CoUninitialize;
end;{------------------------------------------------------------------------------}
procedure TTHDB.ConnectToDatabase;
var
rParam : rConnectionConfig;
begin
rParam := GetConnectionConfig;
rParam.ModuleName := GetTGUIDString;
FDM.InitConnection(rParam);
FDM.Connect;
end;{------------------------------------------------------------------------------}
procedure TThDb.ReStart;
begin
synchronize(
procedure()
begin
LoadData.WorkOnData;
end);
end;{------------------------------------------------------------------------------}
Procedure TTHDB.WorkOnData;
begin
if Assigned(FWhenDone) then FWhenDone(FRet);
Application.ProcessMessages;
end;{------------------------------------------------------------------------------}
function TThDb.LoadData : TThDb;
var
aFiles : TFFilesStatus;
begin
... some work ...
FRet.FValue:=TValue.From<TFFilesStatus>(aFiles);
FRet.FId := FAgs;
result:=Self;
end;{------------------------------------------------------------------------------}
procedure TThDb.Start;
begin
Resume;
end;{------------------------------------------------------------------------------}
procedure TThDb.Execute;
begin
InitializeDatabase;ConnectToDatabase;
restart;
end;
{------------------------------------------------------------------------------}{------------------------------------------------------------------------------}
{------------------------------------------------------------------------------}
and in the frame constructor I have
constructor TFrm.Create(aOwner: TComponent);
begin
inherited Create(aOwner);
FError := TFError.Create;
FTh:=TThDb.Create(True);
FTh.WithOwner(Self).WhenDone(UpdateGrid);
end;and launch the following code ;
var
i : integer;
begin
FTh.Start;
i:=1;
while True do
with FTh do
if Event.waitfor(0)=wrSignaled then
begin
Event.ResetEvent;
WithAgencies(Format('%0.2d',)).ReStart;
inc(i);
if i>99 then i:=1;
if Terminated then Break;
end else Application.ProcessMessages;
FTh.Free;As you see I've a loop ( it's nomal in my test), now If I click again on MyForm Create Thread Button from the main form, I create another TForm with a TFrrame in, and the thread connected to the database from the previous form/frame stop working.
Is it a normal behaviour or am I missing something ? What I would like of course is that both form with thread in are still running.
Thanks for your help
Patrick
-
At the end, it has nothing to do with omnithread, I have the same result with the thread class itself.
I'll move my question (and provide sample) to General Help
Patrick
-
btw ... Delphi 10.3 and omnithread 3.07.7
;-)
-
Hi All
Delphi 10.3 / OmniThread 3.07.7
I'm playing with forms and threads and I'm a little lost...
From a main form (FormMaster) , I have a button, when I click on it , it create another form (FormGrid)
in FormGrid (1), I create a class (TFOmniDb) and create everything within the Thread (as the two fish sample) and update a grid on (1).
now, If I create another FormGrid (2), and launch also the thread, then eveything on (1) stop instead of running in background)
Could yoy help me to find the way of doing it ?
Regards
Patrick
TFOmniDb = class
private
FId : string;
FDo : TpDo;
FDm : TDM;
FWorker : IOmniBackgroundWorker;
FRConfig : RConnectionConfig;
FPrcDone : TOmniWorkItemDoneDelegate;
FPrcToDo : TPrcLoadData;FOnConnectionOpen : TNotify;
procedure InitializeDatabase(var taskState: TOmniValue);
procedure FinalizeDatabase(const taskState: TOmniValue);
procedure ConnectToDatabase(const workItem: IOmniWorkItem);procedure FirstStage(dataModule : TDM);
procedure LoadData(const workItem : IOmniworkItem);
Procedure WorkOnData(const Sender: IOmniBackgroundWorker; const workItem: IOmniWorkItem);
public...
end;{------------------------------------------------------------------------------}
procedure TFOmniDb.AfterConstruction;
begin
inherited;
then FWorker := Parallel.BackgroundWorker
.Initialize(InitializeDatabase)
.Finalize(FinalizeDatabase)
.Execute:
SetThreadDataFactory
in OmniThreadLibrary
Posted · Edited by PatV
update
Hi,
could someone tell me what's wrong here, I'm returning an IInterface as needed so ...
[dcc32 Error] clsInit.pas(313): E2250 There is no overloaded version of 'SetThreadDataFactory' that can be called with these arguments
( in OtlThreadPool ; TOTPThreadDataFactoryFunction = function: IInterface; )
function TFConfig.CreateThreadPool(aHandle : THandle ; aConfig : rConnectionConfig ; aValue: string) : iOmniThreadPool;
begin
result := otlThreadPool.CreateThreadPool(aValue);
result.MaxExecuting := result.NumCores;
result.SetThreadDataFactory
(
function : IInterface
begin
result:=CreateConnectionPoolData(aHandle,aConfig);
end
);
end;
I have defined CreateConnectionPoolData as follow
function CreateConnectionPoolData(const aHandle : THandle ; const aConfig : rConnectionConfig) : IInterface;
var
aPool : IConnectionPoolData;
begin
aPool := TConnectionPoolData.Create;
aPool.WithHandle(aHandle).WithConnectionConfig(aConfig);
result:=aPool;
end;
IConnectionPoolData = interface
function WithHandle(const aValue : HWND) : IConnectionPoolData ;
function WithConnectionConfig(aValue : rConnectionConfig) : IConnectionPoolData ;
end;
Thanks
Patrick