Delphi 2007 AsyncMultiSync不起作用

时间:2015-10-08 07:25:45

标签: multithreading delphi delphi-2007

我尝试使用AsyncCall编写并行线程示例,以下是并行计算素数的数量

program Project3;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Math,
  Windows,
  AsyncCalls in 'AsyncCalls.pas';

const
  N = 1000000;
  MAXT = 100;

var
  threads : array of IAsyncCall;
  ans: array of integer;
  cnt: DWORD;
  i, v, j, k, portion: integer;

function IsPrime(x: integer): boolean;
var
  i: integer;
begin
  if (x <= 1) then 
  begin
    Result := False;
    Exit;
  end;
  if (x = 2) then
  begin
    Result := True;
    Exit;
  end;
  for i:= 2 to Ceil(Sqrt(x))do
  begin
    if (x mod i = 0) then
    begin
      Result := False;
      Exit;
    end;
  end;
  Result := True;
end;

procedure DoWork(left, right: integer; value: PInteger); cdecl;
var
  i, cnt: integer;
begin
  cnt := 0;
  for i := left to right do
  begin
    if (IsPrime(i)) then
    begin
      Inc(cnt);
    end;
  end;
  value^ := cnt;
end;

begin
  // Paralell
  cnt := GetTickCount;
  SetLength(ans, MAXT);
  SetLength(threads, MAXT);
  portion := N div MAXT;
  for i := 0 to MAXT - 2 do
  begin
    // left index
    j := i * portion;
    // right index
    k := (i + 1) * portion - 1;
    threads[i] := AsyncCall(@DoWork, [j, k, @ans[i]]);
  end;
  // last thread
  j := (MAXT - 1) * portion;
  threads[MAXT - 1] := AsyncCall(@DoWork, [j, N - 1, @ans[MAXT - 1]]);
  // Join, doesn't seem to wait all
  AsyncMultiSync(threads, True, INFINITE);
  // ****Adding a delay to wait for all threads*****
  // Sleep(1000);
  // Sum the answer
  v := 0;
  for i := 0 to MAXT - 1 do
  begin
    Inc(v, ans[i]);
  end;
  Writeln('Parallel = ', GetTickCount - cnt);
  Writeln('Answer = ', v);  
  // Serial
  cnt := GetTickCount;
  DoWork(0, N - 1, @v);
  Writeln('Serial = ', GetTickCount - cnt);
  Writeln('Answer = ', v);  
  Readln;
end.

奇怪的行为。 AsyncMultiSync似乎根本没有等待。如果我不添加Sleep(1000),则输出为

Parallel = 172
Answer = 0
Serial = 453
Answer = 78498

如果我添加Sleep(1000),则输出正确:

Parallel = 1188
Answer = 78498
Serial = 265
Answer = 78498

我尝试使用线程[i] .Sync,它会产生类似的结果。

我在这里错过了什么吗?

环境是D2007,Windows 10 64位主页

1 个答案:

答案 0 :(得分:3)

Documentation表示不要超过最大等待对象数,61。

所以你必须减少MaxT常数。