如何从Delphi xe2中的OTL终止parallel.foreach

时间:2014-03-18 23:09:21

标签: delphi foreach parallel-processing omnithreadlibrary

我正在学习如何在Delphi XE2中使用OmniThreadLibrary,我想知道是否有人可以告诉我如何取消parallel.foreach。

我读到我应该使用取消令牌,但我找不到某种关于如何使用它的例子。

这是函数内部的原始循环。

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;

这就是我使用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;

在Parallel.ForEach中,我不能Result := 'ERROR',因为它没有在程序中捕获,所以我想如果我可以取消Parallel.ForEach并报告取消,那么我可以只分配{{ 1}}外面。

但我是OmniThreadLibrary的新手,我不知道怎么做这样的事情,请帮帮我:)

2 个答案:

答案 0 :(得分:0)

您需要使用取消令牌:

var
  cancelToken: IOmniCancellationToken;

您可以通过CreateOmniCancellationToken单元中的OtlSync来获取取消令牌。

cancelToken := CreateOmniCancellationToken;

然后将令牌提供给并行循环:

Parallel.ForEach(...)
    .CancelWith(cancelToken)
    .Execute(...);

您通过调用Signal方法发出取消令牌信号。

cancelToken.Signal;

从并行循环外部可以使用

cancelToken.IsSignaled

检测到您已取消。或者,您可以从周围范围捕获布尔变量,并通过该变量传递信息。

示例here给出了说明。

答案 1 :(得分:0)

取消令牌只有一半。如果你需要它来返回一个值,你需要使用Aggregate,因为你可以在序列中有任意数量的元素,但只有一个返回值,所以你需要折叠(聚合)一个任意的返回值的数量为一个最终值。所以你想要这样的东西:

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;

这可能不完美,但它应该让你走上正轨。