我正在使用XE8,我正在尝试构建一个真实世界应用程序的示例。
我需要在主“服务线程”和OTL线程池之间进行通信。 这些示例都是使用表单和监视器设置的。我不需要那些,但我无法想出一种编写干净代码的方法。到目前为止,这就是我所做的:
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;
实施为:
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;
在主线程中,要创建池,我正在调用:
FThreadPool := CreateThreadPool('Thread pool test');
和
var
lFolder : String;
Process : IOmniWorker;
begin
lFOlder := ExtractFilePath(ParamStr(0));
Process := TProcessWorker.Create;
CreateTask( Process, 'Task test').Unobserved.SetParameter('Folder',lFolder).Schedule(FThreadPool);
我不知道如何正确调用我的工作线程。在我的实际应用程序中,将触发几个线程,我需要确保正确使用线程池。
1)通过像我一样调用CreateTask,我如何正确使用线程池?对于我需要的每个进程调用CreateTask似乎很奇怪。
2)永远不会触发工作线程。我应该如何使我的工作线程工作! :)
此致 克莱门特
答案 0 :(得分:0)
检查http://otl.17slon.com/book/doku.php?id=book:howto:connectionpool
我的感觉是OTL基于数据容器,而不是线程。
所以我认为你需要建立一个任务请求队列,你的“主线程”会将任务注入其中。
池的想法是他们自己管理!你不应该与特定的工作线程进行通信,你应该只是将工作请求发送到它,然后让池产生/杀死工作线程。如果您需要来自每个特定线程的反馈,我宁愿将TForm.Handle或者TOmniMonitor指针包含到任务请求记录中,并让工作线程回调并与表单进行通信,而不是来自螺纹
答案 1 :(得分:0)
OmniThreadLibrary test 08_RegisterComm
显示了如何在两个线程之间直接通信。
基本上,您必须创建IOmniTwoWayChannel
的实例,并使用Initialize
在工作人员的Task.RegisterComm(<channel>)
方法中注册其端点。
然后,您可以在“正常”状态下发送消息。与<channel>.Send(<message>, <data>)
的方式,如果你用Delphi方式装饰它们,它们将被分派到其他任务的消息方法:
procedure MessageHandler(var msg: TOmniMessage); message <message>;