【问题标题】:TParallel.For: Store values in a TList while they are calculated in a TParallel.For loopTParallel.For:将值存储在 TList 中,同时在 TParallel.For 循环中计算它们
【发布时间】:2016-05-30 19:58:02
【问题描述】:

我想使用TParallel.&For循环来计算例如1到100000之间的素数并将所有这些素数保存在AList: TList<Integer>中:

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
  AList: TList<Integer>;
  LoopResult: Tparallel.TLoopResult;
begin
  AList:=TList<Integer>.Create;
  TParallel.&For(1, 100000,
    procedure(AIndex: Integer)
    begin
      if IsPrime(AIndex) then
      begin
        //add the prime number to AList
      end;
    end);

  //show the list
  for i := 0 to AList.Count-1 do
  begin
    Memo1.Lines.Add(IntToStr(AList[i]));
  end;

end;

计算可以并行执行而不会出现问题,但TList 是共享资源。如何以线程安全的方式将已确认的素数添加到列表中?

【问题讨论】:

  • Yoy 会简单地调用AList.Add(AIndex),然后在循环结束后调用Sort() 列表。但是TList 不是线程安全的,因此您需要锁定Add(),例如TCriticalaSection 或TMutex。
  • @RemyLebeau 谢谢。您能否编辑我的代码示例,以便我可以看到TCriticalSection 或TMutex 在这种情况下是如何使用的? TCriticalSection 和 TMutex 之间的优缺点是什么?

标签: multithreading delphi parallel-processing delphi-10.1-berlin


【解决方案1】:

您只需调用AList.Add(AIndex),然后在循环结束后调用Sort() 列表。但是TList 不是线程安全的,所以你需要锁定Add(),比如TCriticalSection 或TMutex:

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
  AList: TList<Integer>;
  ALock: TCriticalSection;
  LoopResult: TParallel.TLoopResult;
begin
  AList := TList<Integer>.Create;
  ALock := TCriticalSection.Create;

  TParallel.&For(1, 100000,
    procedure(AIndex: Integer)
    begin
      if IsPrime(AIndex) then
      begin
        ALock.Enter;
        try
          AList.Add(AIndex);
        finally
          ALock.Leave;
        end;
      end;
    end);

  AList.Sort;
  for i := 0 to AList.Count-1 do
  begin
    Memo1.Lines.Add(IntToStr(AList[i]));
  end;

  ALock.Free;
  AList.Free;
end;

或者改用TThreadList&lt;T&gt;:

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
  AList: TThreadList<Integer>;
  LList: TList<Integer>;
  LoopResult: TParallel.TLoopResult;
begin
  AList := TThreadList<Integer>.Create;

  TParallel.&For(1, 100000,
    procedure(AIndex: Integer)
    begin
      if IsPrime(AIndex) then
      begin
        AList.Add(AIndex);
      end;
    end);

  LList := AList.LockList;
  try
    LList.Sort;
    for i := 0 to LList.Count-1 do
    begin
      Memo1.Lines.Add(IntToStr(LList[i]));
    end;
  finally
    AList.UnlockList;
  end;

  AList.Free;
end;

【讨论】:

  • “与”?真的吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-06
  • 2011-02-10
  • 1970-01-01
  • 2020-02-07
  • 2016-01-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多