安迪开发的这个图书馆AsynCalls给我留下了深刻的印象。
我写了一段代码只是为了测试库,但它总是得到内存A / V,我在这里错过了什么吗?
以下代码旨在使用两个异步线程并行执行此简单任务(从数组中获取最大值)。
program Test;
{$APPTYPE CONSOLE}
uses
SysUtils,
Math,
Windows,
Forms,
AsyncCalls in 'AsyncCalls.pas';
var
arr: array of integer;
i: integer;
procedure GetMax(const arr: array of integer; left, right: integer; var max: integer);
var
i: integer;
begin
max := arr[left];
for i := left + 1 to right do
begin
if (arr[i] > max) then
begin
max := arr[i];
end;
end;
end;
const
N = 100000;
var
a, b: IAsyncCall;
maxv, max1, max2: integer;
begin
SetLength(arr, N);
maxv := -1;
for i := 0 to High(arr) do
begin
arr[i] := RandomRange(0, MaxInt);
if (arr[i] > maxv) then
begin
maxv := arr[i];
end;
end;
a := AsyncCall(@GetMax, [arr, 0, Length(arr) div 2, max1]);
b := AsyncCall(@GetMax, [arr, (Length(arr) div 2) + 1, High(arr), max2]);
while (AsyncMultiSync([a, b], True, 10) = WAIT_TIMEOUT) do
begin
Application.ProcessMessages;
end;
Writeln(max1, ', ', max2, ', ', Max(max1, max2));
Writeln(maxv);
Readln;
end.
答案 0 :(得分:8)
您正在尝试使用AsyncCall
的变量参数版本。该代码表示支持以下类型:
Supported types: Integer : Arg: Integer Boolean : Arg: Boolean Char : Arg: AnsiChar WideChar : Arg: WideChar Int64 : [const] Arg: Int64 Extended : [const] Arg: Extended Currency : [const] Arg: Currency String : [const] Arg: ShortString Pointer : [const] Arg: Pointer PChar : [const] Arg: PChar Object : [const] Arg: TObject Class : [const] Arg: TClass AnsiString : [const] Arg: AnsiString UnicodeString: [const] Arg: UnicodeString PWideChar : [const] Arg: PWideChar WideString : [const] Arg: WideString Interface : [const] Arg: IInterface Variant : const Arg: Variant
您的函数会收到一个打开的数组参数和一个var
参数,这两个参数都没有在上面的列表中找到。此外,该函数必须使用cdecl
调用约定。
以下是您的代码的一个版本:
program Test;
{$APPTYPE CONSOLE}
uses
SysUtils,
Math,
AsyncCalls in 'AsyncCalls.pas';
var
arr: array of integer;
procedure GetMax(left, right: integer; max: PInteger); cdecl;
var
i: integer;
begin
max^ := arr[left];
for i := left + 1 to right do
begin
if (arr[i] > max^) then
begin
max^ := arr[i];
end;
end;
end;
const
N = 100000;
var
a, b: IAsyncCall;
i, maxv, max1, max2: integer;
begin
SetLength(arr, N);
maxv := -1;
for i := 0 to High(arr) do
begin
arr[i] := RandomRange(0, MaxInt);
if (arr[i] > maxv) then
begin
maxv := arr[i];
end;
end;
a := AsyncCall(@GetMax, [0, Length(arr) div 2, @max1]);
b := AsyncCall(@GetMax, [(Length(arr) div 2) + 1, High(arr), @max2]);
AsyncMultiSync([a, b], True, INFINITE);
Writeln(max1, ', ', max2, ', ', Max(max1, max2));
Writeln(maxv);
Readln;
end.
请注意,我做了以下更改:
Forms
的使用以及对ProcessMessages
的调用。GetMax
使用cdecl
调用约定。max
作为指向整数而不是var
参数的指针。这是因为不支持var
参数。GetMax
使用全局变量arr
,而不是将其作为参数接收。这是为了权宜之计。另一种方法是传递第一个元素的地址。坦率地说,你的代码足够复杂,使变量参数AsyncCall
感觉有点拉长。您可能最好传递一个对象或一个指向记录的指针,而不是使用变量参数重载。
我还应该指出,不再开发AsyncCalls。在我看来,采用OTL而不是AsyncCalls会更好地服务。