简体   繁体   English

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

[英]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 example here gives an illustration. 这里的例子举例说明。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM