OmniThreadLibrary: How to run Parallel.For.Execute without using anonymous procedure?

175 views Asked by At

The Execute method of Parallel.For has a TOmniIteratorDelegate parameter. But I'm unsure on how to assign a procedure to a variable of that type. The reason for doing this is that I do not want to use anonymous procedures.

Is this possible? If yes, can someone show me how to do it?

type
  TBookmark = record
    URL: String;
    PageTitle: String;
  end;

  PBookmark = ^TBookmark;

var
  FBookmarkList: TThreadList<PBookmark>;

procedure TfmMain.FormCreate(Sender: TObject);
begin
  FBookmarkList := TThreadList<PBookmark>.Create;

end;

procedure TfmMain.FormDestroy(Sender: TObject);
var
  B: PBookmark;
  L: TList<PBookmark>;
begin
  L := FBookmarkList.LockList;
  for B in L do
    Dispose(B);
  FBookmarkList.UnlockList;
  FBookmarkList.Free;
end;

procedure SetValue(const Value: TOmniValue);
begin
  // P := Value.ToRecord<PBookmark>;
  // P.PageTitle := P.URL;

end;

procedure TfmMain.btRefreshClick(Sender: TObject);
var
  L: TList<PBookmark>;
  P: TOmniIteratorDelegate<PBookmark>;
  t: IOmniParallelLoop<PBookmark>;
begin

  P := TOmniIteratorDelegate<PBookmark>(Addr(SetValue)); // <---- Program crashes at runtime on this line!

  L := FBookmarkList.LockList;
  try
    t := Parallel.ForEach<PBookmark>(L).NumTasks(5);
    t.Execute(P);

    vstBkmk.Clear;
    FvstBkmkIter := 0;
    vstBkmk.RootNodeCount := L.Count;
  finally
    FBookmarkList.UnlockList;
  end;

end;
1

There are 1 answers

0
Steve F On

I got it to work by changing the definition of the SetValue procedure as illustrated in the code below. Thanks to David Heffernan for pointing me in the right direction.

procedure SetValue(const Value: PBookmark);
var
  P: PBookmark;
begin
  Value.PageTitle := Value.URL;
end;

procedure TfmMain.btRefreshClick(Sender: TObject);
var
  L: TList<PBookmark>;
  P: TOmniIteratorDelegate<PBookmark>;
  t: IOmniParallelLoop<PBookmark>;
begin

  P := SetValue;

  L := FBookmarkList.LockList;
  try
    t := Parallel.ForEach<PBookmark>(L).NumTasks(5);
    t.Execute(P);

    vstBkmk.Clear;
    FvstBkmkIter := 0;
    vstBkmk.RootNodeCount := L.Count;
  finally
    FBookmarkList.UnlockList;
  end;

end;