gpt4 book ai didi

Delphi AsyncCalls 访问冲突

转载 作者:行者123 更新时间:2023-12-03 14:42:06 29 4
gpt4 key购买 nike

这个图书馆给我留下了深刻的印象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.

最佳答案

您正在尝试使用 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

Your function receives an open array parameter and a var parameter, neither to be found in the list above. What's more, the function must use the cdecl calling convention.

Here is a version of your code that does work:

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.

请注意,我进行了以下更改:

  1. 删除了 Forms 的使用以及对 ProcessMessages 的调用。
  2. 使 GetMax 使用 cdecl 调用约定。
  3. max 作为指向整数的指针而不是 var 参数传递。这是因为不支持 var 参数。
  4. GetMax 使用全局变量 arr 而不是将其作为参数接收。那是为了权宜之计。另一种方法可能是传递第一个元素的地址。

坦率地说,您的代码足够复杂,足以使变量参数 AsyncCall 感觉有点捉襟见肘。您可能最好传递一个对象或指向记录的指针,而不是使用变量参数重载。

<小时/>

我还应该指出,AsyncCalls 已不再开发。在我看来,采用 OTL 比采用 AsyncCalls 会更好。

关于Delphi AsyncCalls 访问冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23896870/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com