[英]How to terminate a parallel.foreach from OTL in Delphi xe2
I am learning how to use OmniThreadLibrary in Delphi XE2, i wonder if someone can show me how to cancel a parallel.foreach. 我正在学习如何在Delphi XE2中使用OmniThreadLibrary,我想知道是否有人可以告诉我如何取消parallel.foreach。
I read that I should use a cancellation token, but I cannot find an example of some sort on how to use it. 我读到我应该使用取消令牌,但我找不到某种关于如何使用它的例子。
This is the original for loop inside the function. 这是函数内部的原始循环。
function SomeFunction() : string;
begin
for value := 0 to length(listOfThings)-1 do
begin
Chain := Function1( listOfThings[value] );
if Evaluate( Chain , Solution) then
Parameters[value] := Solution
else
begin
Result := 'ERROR';
exit;
end;
end;
end;
And this is how I am using the Parallel.ForEach 这就是我使用Parallel.ForEach的方式
function SomeFunction() : string;
begin
Parallel.ForEach(0, length(listOfThings)-1 ).Execute(
procedure (const value: integer)
var Chain : string;
begin
Chain := Function1(listOfThings[value]);
if Evaluate(Chain , Solution) then
Parameters[value] := Solution
else
begin
Result := 'ERROR'; //Here is where it won't work
exit;
end;
end
);
end;
Inside the Parallel.ForEach I can't do Result := 'ERROR'
because it is not captured inside the procedure, so I think if I can cancel the Parallel.ForEach and report that cancellation, then I can just assign Result := 'ERROR'
outside. 在Parallel.ForEach里面我不能做Result := 'ERROR'
因为它没有在程序中捕获,所以我想如果我可以取消Parallel.ForEach并报告取消,那么我可以只分配Result := 'ERROR'
在外面。
But I am new to OmniThreadLibrary and I don't know how to do such a thing, please help me :) 但我是OmniThreadLibrary的新手,我不知道怎么做这样的事情,请帮帮我:)
You need to use a cancellation token: 您需要使用取消令牌:
var
cancelToken: IOmniCancellationToken;
You obtain the cancellation token by calling CreateOmniCancellationToken
from the OtlSync
unit. 您可以通过从OtlSync
单元调用CreateOmniCancellationToken
来获取取消令牌。
cancelToken := CreateOmniCancellationToken;
You then supply the token to the parallel loop: 然后,您将令牌提供给并行循环:
Parallel.ForEach(...)
.CancelWith(cancelToken)
.Execute(...);
And you signal the cancellation token by calling its Signal
method. 并通过调用其Signal
方法向取消令牌发出Signal
。
cancelToken.Signal;
From outside the parallel loop you can use 从并行循环外部可以使用
cancelToken.IsSignaled
to detect that you cancelled. 检测到你取消了。 Or you can capture a boolean variable from the surrounding scope and pass the information through that variable. 或者,您可以从周围范围捕获布尔变量,并通过该变量传递信息。
The cancellation token is only half of it. 取消令牌只是它的一半。 If you need it to return a value, you'll need to use Aggregate
, because you can have an arbitrary number of elements in the sequence, but only one return value, so you need to collapse (aggregate) an arbitrary number of return values into one final value. 如果你需要它来返回一个值,你需要使用Aggregate
,因为你可以在序列中有任意数量的元素,但只有一个返回值,所以你需要折叠(聚合)任意数量的返回值成为一个最终价值。 So you want something like this: 所以你想要这样的东西:
function SomeFunction() : string;
var
cancelToken: IOmniCancellationToken;
error: TOmniValue;
begin
cancelToken := CreateOmniCancellationToken;
error := Parallel.ForEach(0, length(listOfThings)-1 ).
CancelWith(cancelToken).
Aggregate('',
procedure(var aggregate: TOmniValue; const value: TOmniValue)
var Chain : string;
begin
Chain := Function1(listOfThings[value]);
if Evaluate(Chain , Solution) then
Parameters[value] := Solution
else
begin
aggregate := 'ERROR';
cancelToken.signal;
end;
end).
Execute(
procedure(const value: TOmniValue; var result: TOmniValue)
begin
if value <> '' then
result := value;
end);
if error <> '' then
//something went wrong
end;
This may not be exactly perfect, but it should get you on the right track. 这可能不完美,但它应该让你走上正轨。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.