Multithreading Omnithread:创建一个任务包装器/修改一个任务,该任务向现有任务添加一些额外的预处理和后处理

Multithreading Omnithread:创建一个任务包装器/修改一个任务,该任务向现有任务添加一些额外的预处理和后处理,multithreading,delphi,omnithreadlibrary,Multithreading,Delphi,Omnithreadlibrary,一些背景: 基本上,我希望能够在当前线程中“执行”任务。 为什么?-我有一个task creator例程,一次我希望在后台任务中立即执行该任务,另一次我希望使用IOmniThreadPool调度该任务 在我想使用OmniThreadpool的情况下,我想对任务的状态进行一些输出,比如它已排队、已启动、已完成或已失败 此时任务的执行尚未开始 所以我想象了这样的事情: function WrapIntoPoolTask(const aOriginalTask:IOmniTaskCOntrol):IO

一些背景

基本上,我希望能够在当前线程中“执行”任务。 为什么?-我有一个task creator例程,一次我希望在后台任务中立即执行该任务,另一次我希望使用
IOmniThreadPool
调度该任务

在我想使用OmniThreadpool的情况下,我想对任务的状态进行一些输出,比如它已排队、已启动、已完成或已失败

此时任务的执行尚未开始

所以我想象了这样的事情:

function WrapIntoPoolTask(const aOriginalTask:IOmniTaskCOntrol):IOmniTaskCOntrol;
begin
  if Assigned(aOriginalTask) then
  begin
    var lPoolProgress:=TaskPoolProgress; // fetch global task pool progress interface
    // immediately displays message says its been queued, remember message bookmark
    var lMessageBookMark:=lPoolProgress.MessageList.AddMessage(aOriginalTask.Name,pmPaused);
    Result:=CreateTask(
      procedure (const aTask:IOmniTask)
      begin
        lPoolProgress.MessageList.UpdateMessage(lMessageBookMark,pmStarted); // update message status
        try

          aOriginalTask.ExecuteTaskInThisThread; // <<=== So how do I do this?

          lPoolProgress.MessageList.UpdateMessage(lMessageBookMark,pmCompleted);
        except
          lPoolProgress.MessageList.UpdateMessage(lMessageBookMark,pmFailed);
          raise;
        end;
      end
      ,
      'Pooled:'+aOriginalTask.Name
    );
  end;
end;
函数wrapintopoltask(const aooriginaltask:IOmniTaskCOntrol):IOmniTaskCOntrol;
开始
如果已分配(原始任务),则
开始
var lPoolProgress:=TaskPoolProgress;//获取全局任务池进度接口
//立即显示消息,说明其已排队,记住消息书签
var lMessageBookMark:=lPoolProgress.MessageList.AddMessage(aOriginalTask.Name,pmPaused);
结果:=CreateTask(
程序(const-aTask:IOmniTask)
开始
lPoolProgress.MessageList.UpdateMessage(lMessageBookMark,pmStarted);//更新消息状态
尝试

aooriginaltask.executetaskinthishthread;//为了解决我的问题,我必须稍微更改omnithreadlibrary单元
OtlTaskControl

一个例程添加到
IOmniTaskControl
(GUID应该更改,但我没有更改)

并将实现添加到
TOmniTaskControl

function TOmniTaskControl.DirectExecute:IOmniTaskControl;
VAR lTask:IOmniTask;
begin
  Result:=self;
  lTask:=CreateTask;
  (lTask as IOmniTaskExecutor).Execute;
end;
然后,我的“自定义包装器”例程实际上将池进度处理添加到原始任务中:

function WrapIntoOmniPoolTask(const aTaskControl:IOmniTaskCOntrol):IOmniTaskCOntrol;
var lTaskControl:IOmniTaskCOntrol;
    lPoolProgress:IAppProgress;
    lmbm:integer;
begin
  if Assigned(aTaskControl) then
  begin
    // have some local copies to work around compiler bug RX10.3 and RX10.4
    // cannot use inline vars due to this bug either.
    lTaskControl:=aTaskControl;
    lPoolProgress:=TaskPoolProgress;
    lmbm:=lPoolProgress.MessageList.AddMessage(aTaskControl.Name,pmPaused);
    Result:=CreateTask(
      procedure (const aTask:IOmniTask)
      begin
        try
          lPoolProgress.MessageList.UpdateMessage(lmbm,pmStarted);
          try
            lTaskControl.DirectExecute;
            aTask.SetExitStatus(lTaskControl.ExitCode,lTaskControl.ExitMessage);
            HandlePoolTaskTermination(lTaskControl,lmbm,lPoolProgress);
          except
            HandlePoolTaskTermination(lTaskControl,lmbm,lPoolProgress);
            if IsFatalException then
              raise;
          end;
        finally
          // release interfaces when all is done
          lPoolProgress:=nil; 
          lTaskControl:=nil;
        end;
      end,
      'Pooled: '+lTaskCOntrol.Name
    );
  end;
end;

最后,将包装好的任务安排到omnipoolthread中的例程

function TfrmMain.CreateTestTask:IOmniTaskControl;
begin
  Result:=WrapIntoOmniPoolTask(CreateTask(TestTask,TGUID.NewGuid.ToString)).Unobserved;
end;
一切似乎都按预期工作,包括从内部任务传播到外部任务的退出代码和退出消息

我提到的编译器错误在这里有报道:(请投票!)


对于感兴趣的人:这是
HandlePool任务终止
的样子:

procedure HandlePoolTaskTermination(const aTaskControl:IOmniTaskCOntrol;const aMessageBookmark:integer;const aPoolProgress:IAppProgress);
begin
  var pm:=pmCompleted;
  if Assigned(aTaskControl.FatalException) then
  begin
    pm:=pmWarning;
    var pe:=peError;
    if IsAbortException(aTaskControl.FatalException) then
      pe:=peWarning
    else if IsFatalException(aTaskControl.FatalException) then
    begin
      pm:=pmFailed;
      pe:=peFatalError;
    end;
    aPoolProgress.ErrorList.AddErrorToMessage(aMessageBookmark,'',pe,aTaskControl.FatalException)
  end
  else if aTaskControl.ExitCode<>0 then
  begin
    pm:=pmWarning;
    aPoolProgress.ErrorList.AddErrorToMessage(aMessageBookmark,aTaskControl.ExitMessage,peWarning);
  end;
  aPoolProgress.MessageList.UpdateMessage(aMessageBookmark,pm);
end;
过程HandlePoolTaskTermination(常量aTaskControl:IOmniTaskCOntrol;常量aMessageBookmark:integer;常量aPoolProgress:IAppProgress);
开始
var pm:=pmCompleted;
如果已分配(aTaskControl.FatalException),则
开始
pm:=pm警告;
var pe:=peError;
如果IsAbortException(aTaskControl.FatalException),则
pe:=pe警告
否则如果是FatalException(aTaskControl.FatalException),则
开始
pm:=pm失败;
pe:=peFatalError;
结束;
aPoolProgress.ErrorList.AddErrorToMessage(aMessageBookmark',pe,aTaskControl.FatalException)
结束
否则,如果aTaskControl.ExitCode0,则
开始
pm:=pm警告;
aPoolProgress.ErrorList.adderrortmessage(aMessageBookmark、aTaskControl.ExitMessage、peWarning);
结束;
aPoolProgress.MessageList.UpdateMessage(aMessageBookmark,pm);
结束;
如果“当前”异常为例如
eaccessinvalition
EINValidoOperation
等,则
IsFatalException
返回true。仅供参考:“DirectExecute”已添加到OmniThreadLibrary的“官方”源中。请查看github。
procedure HandlePoolTaskTermination(const aTaskControl:IOmniTaskCOntrol;const aMessageBookmark:integer;const aPoolProgress:IAppProgress);
begin
  var pm:=pmCompleted;
  if Assigned(aTaskControl.FatalException) then
  begin
    pm:=pmWarning;
    var pe:=peError;
    if IsAbortException(aTaskControl.FatalException) then
      pe:=peWarning
    else if IsFatalException(aTaskControl.FatalException) then
    begin
      pm:=pmFailed;
      pe:=peFatalError;
    end;
    aPoolProgress.ErrorList.AddErrorToMessage(aMessageBookmark,'',pe,aTaskControl.FatalException)
  end
  else if aTaskControl.ExitCode<>0 then
  begin
    pm:=pmWarning;
    aPoolProgress.ErrorList.AddErrorToMessage(aMessageBookmark,aTaskControl.ExitMessage,peWarning);
  end;
  aPoolProgress.MessageList.UpdateMessage(aMessageBookmark,pm);
end;