Delphi - OTL - 线程池和工作线程之间的通信

Posted

技术标签:

【中文标题】Delphi - OTL - 线程池和工作线程之间的通信【英文标题】:Delphi - OTL - Communicating between ThreadPool and Worker thread 【发布时间】:2015-05-26 23:42:22 【问题描述】:

我正在使用 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) 工作线程永远不会被触发。我应该如何让我的 Worker 线程工作! :)

问候, 克莱门特

【问题讨论】:

【参考方案1】:

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

我的感觉是 OTL 是基于数据容器,而不是线程。

所以我认为您需要创建一个任务请求队列,您的“主线程”会将任务注入其中。

池的想法是它们自己管理!你不应该与特定的工作线程通信,你应该只向它发送工作请求,然后让池在它认为合适的时候生成/杀死工作线程。

如果您需要来自每个特定线程的反馈,我宁愿将 TForm.Handle 或 TOmniMonitor 指针包含到任务请求记录中,并让工作线程回调并与表单进行通信,而不是 from 与线程

【讨论】:

【参考方案2】:

OmniThreadLibrary 测试08_RegisterComm 展示了如何在两个线程之间直接通信。

基本上,您必须创建一个IOmniTwoWayChannel 的实例,并使用Task.RegisterComm(<channel>) 在worker 的Initialize 方法中注册其端点。

然后,您可以使用<channel>.Send(<message>, <data>) 以“正常”方式发送消息,如果您以 Delphi 方式装饰,它们将被分派到其他任务的消息方法:

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

【讨论】:

以上是关于Delphi - OTL - 线程池和工作线程之间的通信的主要内容,如果未能解决你的问题,请参考以下文章

在 MainForm 关闭 OTL 线程不关闭

线程池和异步线程

线程池和异步线程

4种线程池和7种并发队列

线程池和数据库连接池

线程池和动态变化的工人数量