ドキュメントを読んだ後、OmniThreadLibrary をいじっているだけですが、ParallelTask の構築に関する簡単な/初期の問題にまだ直面しています。
cancellationToken
とterminationHandler
を使用した ParallelTask の構築後、非同期実行が完了した後に実行さterminationHandler.OnTerminated
れOnStop
ず、理由を見つけることができませんでした:-(
OTL の専門家の何人かが、これについて私を助けてくれることを願っています。
私が達成したいこと:
- 非同期操作を実行する
- キャンセル時に実行を停止 (cancellationtoken)
- 非同期操作が完了すると、メインスレッドでコードを実行します (例外をチェックします)。
私がこれまでにやったこと:
ドキュメントを読んだ後、ParallelTask を作成し、セットアップしcancellationToken
て操作terminationHandler
をTaskConfig
実行しました。実行された操作自体は、cancellationToken
シグナルが送信されていることを確認し、その作業を行います (ここでは 1 のスリープ)。このHandleOnTerminated
メソッドはエラーをチェックし、fIsDone フラグと fHasError フラグを設定して、メインスレッドから読み取ります。
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.