2

使用 OmniThreadLibrary 和 Delphi XE4,我希望在后台运行多个线程来处理数据,从而提高我现有代码的速度。

调用以下过程时,应用程序 GUI 将停止处理任何输入,直到所有线程都完成。我的理解是.NoWait即使线程正在运行,使用也应该允许过程退出。

procedure Test(input: TStringList; output: TList<TMaintFore>);
var
  outQueue: IOmniBlockingCollection;
  transaction: TOmniValue;
begin
  outQueue := TOmniBlockingCollection.Create;
  Parallel.ForEach(0, input.Count - 1)
    .NoWait
    .Into(outQueue)
    .Execute(
      procedure(const value: integer; var result: TOmniValue)
      begin
        result := TMaintFore.Create(input[value]);
      end
    );
end;

是不是我对 ForEach 循环的理解不正确,提示我应该使用另一种方法来实现后台处理?感谢您对正确使用 OmniThreadLibrary 的任何建议。

4

1 回答 1

10

您必须将从 Parallel.ForEach 返回的接口存储在全局(表单等)变量中,并仅在 ForEach 完成执行时销毁它。

在您的示例中, ForEach 的结果存储在一个临时变量中,该变量在 Test 过程退出时被销毁。ForEach 析构函数等待所有任务完成并阻塞您的程序。

在任务完成时销毁 foreach 接口的最安全(但不可否认)的方法是使用 OnStop 方法并从中将命令排队到主线程。

var
  loop: IOmniParallelLoop<integer>;

loop := Parallel.ForEach(1, N).NoWait;
loop.OnStop(
  procedure (const task: IOmniTask)
  begin
    task.Invoke(
      procedure
      begin
        // do anything
        loop := nil;
      end);
  end);
loop.Execute(
  procedure (const value: integer)
  begin
    ...
  end);

这记录在wiki中。

于 2013-06-02T07:38:22.470 回答