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