Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 如何使用异步调用调用无参数类过程?_Multithreading_Delphi_Delphi 7 - Fatal编程技术网

Multithreading 如何使用异步调用调用无参数类过程?

Multithreading 如何使用异步调用调用无参数类过程?,multithreading,delphi,delphi-7,Multithreading,Delphi,Delphi 7,试图集成到我的Delphi7项目中,我还不能调用类的无参数过程 我想做的是: 这是不可能的,导致错误E2036 Variable required当您尝试获取表达式或常量的地址时,会出现此错误消息 无论何时,只要我的过程有像本文中的WaitForItprocedure这样的参数,这都是可能的。 此外,LocalAsyncCall也是可能的,但我并不总是想声明本地过程 如果我将这个过程设置为静态的,也可以调用它,即过程TestCalculation,而不是过程TMyForm.tesculation

试图集成到我的Delphi7项目中,我还不能调用类的无参数过程

我想做的是:

这是不可能的,导致错误E2036 Variable required当您尝试获取表达式或常量的地址时,会出现此错误消息

无论何时,只要我的过程有像本文中的WaitForItprocedure这样的参数,这都是可能的。 此外,LocalAsyncCall也是可能的,但我并不总是想声明本地过程

如果我将这个过程设置为静态的,也可以调用它,即过程TestCalculation,而不是过程TMyForm.tesculation。然后我可以成功调用RunTestCall:=AsyncCall@TestCalculation, []; 但这不适用于属于TMyForm的过程

问题:

在我的示例TestCalculation中,如何使用来自类中另一个过程的异步调用调用无参数类过程?

AsyncCall希望您传递一个接收一个参数的过程。如果不想传递参数,只需添加一个并忽略它

procedure TestCalculation(IgnoreMe: Integer);
....
TestCall := AsyncCall(TestCalculation, 0);
您可以编写适配器,使调用方的代码更干净:

type
  TAsyncCallParameterlessProc = procedure of object;

function AsyncCall(Proc: TAsyncCallParameterlessProc): IAsyncCall; overload;

......

type
  TAsyncCallParameterlessProcAdapter = class
  private
    FProc: TAsyncCallParameterlessProc;
  public
    constructor Create(Proc: TAsyncCallParameterlessProc);
    procedure IntegerProc(IgnoreMe: Integer);
  end;

{ TAsyncCallParameterlessProcAdapter }

constructor TAsyncCallParameterlessProcAdapter.Create(
  Proc: TAsyncCallParameterlessProc);
begin
  inherited Create;
  FProc := Proc;
end;

procedure TAsyncCallParameterlessProcAdapter.IntegerProc(IgnoreMe: Integer);
begin
  try
    FProc;
  finally
    Free;
  end;
end;

function AsyncCall(Proc: TAsyncCallParameterlessProc): IAsyncCall;
var
  Adapter: TAsyncCallParameterlessProcAdapter;
begin
  Adapter := TAsyncCallParameterlessProcAdapter.Create(Proc);
  Result := AsyncCall(Adapter.IntegerProc, 0);
end;
有了这个适配器,问题中的代码就可以编译并工作了

由于异步调用已中断,并且不会再次修改,因此您可以很容易地修改该代码以支持所需的使用

就我个人而言,我会修改AsyncCalls并添加另一个子类TInternalAsyncCall来完成这项工作

作为一个真正肮脏的黑客,这将起作用:

type
  TAsyncCallParameterlessProc = procedure of object;

function AsyncCall(Proc: TAsyncCallParameterlessProc): IAsyncCall; overload;

.....

function AsyncCall(Proc: TAsyncCallParameterlessProc): IAsyncCall;
begin
  Result := AsyncCall(TAsyncCallArgIntegerEvent(Proc), 0);
end;
这取决于整型参数TAsyncCallArgIntegerEvent在易失性寄存器中传递的事实。因此,当框架传递0时,您的过程不会从寄存器中读取它。

AsyncCall期望您传递一个接收一个参数的过程。如果不想传递参数,只需添加一个并忽略它

procedure TestCalculation(IgnoreMe: Integer);
....
TestCall := AsyncCall(TestCalculation, 0);
您可以编写适配器,使调用方的代码更干净:

type
  TAsyncCallParameterlessProc = procedure of object;

function AsyncCall(Proc: TAsyncCallParameterlessProc): IAsyncCall; overload;

......

type
  TAsyncCallParameterlessProcAdapter = class
  private
    FProc: TAsyncCallParameterlessProc;
  public
    constructor Create(Proc: TAsyncCallParameterlessProc);
    procedure IntegerProc(IgnoreMe: Integer);
  end;

{ TAsyncCallParameterlessProcAdapter }

constructor TAsyncCallParameterlessProcAdapter.Create(
  Proc: TAsyncCallParameterlessProc);
begin
  inherited Create;
  FProc := Proc;
end;

procedure TAsyncCallParameterlessProcAdapter.IntegerProc(IgnoreMe: Integer);
begin
  try
    FProc;
  finally
    Free;
  end;
end;

function AsyncCall(Proc: TAsyncCallParameterlessProc): IAsyncCall;
var
  Adapter: TAsyncCallParameterlessProcAdapter;
begin
  Adapter := TAsyncCallParameterlessProcAdapter.Create(Proc);
  Result := AsyncCall(Adapter.IntegerProc, 0);
end;
有了这个适配器,问题中的代码就可以编译并工作了

由于异步调用已中断,并且不会再次修改,因此您可以很容易地修改该代码以支持所需的使用

就我个人而言,我会修改AsyncCalls并添加另一个子类TInternalAsyncCall来完成这项工作

作为一个真正肮脏的黑客,这将起作用:

type
  TAsyncCallParameterlessProc = procedure of object;

function AsyncCall(Proc: TAsyncCallParameterlessProc): IAsyncCall; overload;

.....

function AsyncCall(Proc: TAsyncCallParameterlessProc): IAsyncCall;
begin
  Result := AsyncCall(TAsyncCallArgIntegerEvent(Proc), 0);
end;

这取决于整型参数TAsyncCallArgIntegerEvent在易失性寄存器中传递的事实。因此,当框架通过0时,您的过程不会从寄存器中读取它。

我认为这是一种解决方法,但它看起来很难看,感觉不对劲。我个人会从代码中使用的名称中删除无参数。如果该过程是带有对象参数的,则定义为TAsyncCallArgObjectProc,因此指定参数的是ArgObject。我会把它作为TAsyncCallProc保存。[+1]经过测试,工作正常。谢谢分享你的智慧;-非常好。我认为这是一个解决办法,但它看起来很难看,感觉不对劲。我个人会从代码中使用的名称中删除无参数。如果该过程是带有对象参数的,则定义为TAsyncCallArgObjectProc,因此指定参数的是ArgObject。我会把它作为TAsyncCallProc保存。[+1]经过测试,工作正常。谢谢分享你的智慧;-非常好。异步调用是否支持匿名方法,如OTL?这样你就可以把那个调用打包成特别的过程了?与AsyncCall过程param类似:integer begin TMyClass.MyMethod;终止或者您可以使用OmniThreadsLibrary?就我所记得的,你只需要Parallel.Async ProcedureName,但你可以检查它。至少OTL没有停止:-不幸的是,OTL不支持Delphi 7。运气不好。OTL v.1.x?虽然1.x也不受支持:-但实际上,您最好标记您的Delphi版本,这是标记的目的之一,毕竟我的AsyncCall问题也解决了其他Delphi版本。我不打算在这里讨论OTL。因此,我认为没有必要使用特定的delphi版本标记。抱歉,这仍然限制了您使用的langauge或RTL功能。即使有人建议您使用AsyncCall的变通方法,他可能会使用一些高级功能,但您事先并不确定。所以我认为一个很好的特点是标记您的Delphi的最低版本——就像任何提供的答案都应该兼容的最低特性库一样。异步调用是否支持匿名方法,比如OTL?这样你就可以把那个调用打包成特别的过程了?与AsyncCall过程param类似:integer begin TMyClass.MyMethod;终止或者您可以使用OmniThreadsLibrary?就我所记得的,你只需要Parallel.Async ProcedureName,但你可以检查它。至少OTL没有停止:-不幸的是,OTL不支持Delphi 7。运气不好。OTL v.1.x?虽然1.x也不受支持:-但实际上,您最好标记您的Delphi版本,这是其中之一
标记的用途毕竟我的异步调用问题也解决了其他Delphi版本。我不打算在这里讨论OTL。因此,我认为没有必要使用特定的delphi版本标记。抱歉,这仍然限制了您使用的langauge或RTL功能。即使有人建议您使用AsyncCall的变通方法,他可能会使用一些高级功能,但您事先并不确定。所以我认为一个很好的特点是标记您的Delphi的最低版本——就像任何提供的答案都应该兼容的最低特性库一样。给我两分钱。