我在阅读文档后正在玩OmniThreadLibrary,但我仍然面临构建ParallelTask的一些简单/早期问题。
在cancellationToken
和terminationHandler
构建ParallelTask之后,异步执行完成后我没有执行terminationHandler.OnTerminated
和OnStop
,我无法找到出于何种原因: - (
我希望一些OTL专业人士可以帮助我解决这个问题。
我想要实现的目标:
到目前为止我做了什么:
阅读文档后,我创建了一个ParallelTask,通过cancellationToken
设置terminationHandler
和TaskConfig
并执行操作。
执行的操作本身会检查发出信号的cancellationToken
并执行其工作(此处为1s的Sleep)。 HandleOnTerminated
方法检查
错误并设置fIsDone和fHasError标志,由来自mainthread的人读取。
unit OTLSetup.Async;
interface
uses
OtlParallel, OtlSync, OtlTaskControl, OtlTask;
type
IAsyncOperation = interface
['{6B10AB46-DEB6-48F5-AC36-E9327AA54C82}']
procedure Execute;
procedure Cancel;
function IsDone: boolean;
end;
TAsyncOperation = class(TInterfacedObject, IAsyncOperation)
protected
fParallelTask: IOmniParallelTask;
fCancellationToken: IOmniCancellationToken;
fIsDone: boolean;
procedure HandleOnTerminated(const task: IOmniTaskControl);
procedure HandleOnStop;
procedure AsyncOperation(const task: IOmniTask);
public
procedure Execute;
procedure Cancel;
function IsDone: boolean;
end;
implementation
uses
Winapi.Windows;
{ TAsyncOperation }
procedure TAsyncOperation.Cancel;
begin
fCancellationToken.Signal;
end;
procedure TAsyncOperation.Execute;
begin
if Assigned(fParallelTask) then
Exit;
fIsDone := false;
fCancellationToken := CreateOmniCancellationToken;
fParallelTask := Parallel.ParallelTask;
fParallelTask.NoWait.NumTasks(1);
fParallelTask.TaskConfig(Parallel.TaskConfig.CancelWith(fCancellationToken).OnTerminated(HandleOnTerminated));
fParallelTask.OnStop(HandleOnStop);
fParallelTask.Execute(AsyncOperation);
end;
procedure TAsyncOperation.AsyncOperation(const task: IOmniTask);
var
I: Integer;
begin
for I := 0 to 5 do
if task.CancellationToken.IsSignalled then
Exit
else
Winapi.Windows.Sleep(1000);
end;
procedure TAsyncOperation.HandleOnStop;
begin
fParallelTask := nil;
fIsDone := true;
end;
procedure TAsyncOperation.HandleOnTerminated(const task: IOmniTaskControl);
begin
fParallelTask := NIL;
fIsDone := true;
end;
function TAsyncOperation.IsDone: boolean;
begin
result := fIsDone;
end;
end.
有了代码的和平,fIsDone
永远不会被设置,因为永远不会调用HandleOnTerminate
和HandleOnStop
。所以从上面的例子
以下ConsoleApplication似乎永远不会结束:
program OTLSetup;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
OTLSetup.Async in 'OTLSetup.Async.pas';
var
LAsync: IAsyncOperation;
begin
LAsync := TAsyncOperation.Create;
try
LAsync.Execute;
while not LAsync.IsDone do
Writeln('Async task still running');
Writeln('Async task finished');
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
答案 0 :(得分:2)
正如评论中所述,我遇到的问题是由consoleapplication本身引起的,因为它不包含messageloop(在我的例子中是一个DUnitX项目)。
由于OTL通信似乎基于windowsmessages,因此在没有工作消息循环的情况下不会触发OnTerminated和OnStop。