Multithreading 如何使用异步调用调用无参数类过程?
试图集成到我的Delphi7项目中,我还不能调用类的无参数过程 我想做的是: 这是不可能的,导致错误E2036 Variable required当您尝试获取表达式或常量的地址时,会出现此错误消息 无论何时,只要我的过程有像本文中的WaitForItprocedure这样的参数,这都是可能的。 此外,LocalAsyncCall也是可能的,但我并不总是想声明本地过程 如果我将这个过程设置为静态的,也可以调用它,即过程TestCalculation,而不是过程TMyForm.tesculation。然后我可以成功调用RunTestCall:=AsyncCall@TestCalculation, []; 但这不适用于属于TMyForm的过程 问题: 在我的示例TestCalculation中,如何使用来自类中另一个过程的异步调用调用无参数类过程?AsyncCall希望您传递一个接收一个参数的过程。如果不想传递参数,只需添加一个并忽略它Multithreading 如何使用异步调用调用无参数类过程?,multithreading,delphi,delphi-7,Multithreading,Delphi,Delphi 7,试图集成到我的Delphi7项目中,我还不能调用类的无参数过程 我想做的是: 这是不可能的,导致错误E2036 Variable required当您尝试获取表达式或常量的地址时,会出现此错误消息 无论何时,只要我的过程有像本文中的WaitForItprocedure这样的参数,这都是可能的。 此外,LocalAsyncCall也是可能的,但我并不总是想声明本地过程 如果我将这个过程设置为静态的,也可以调用它,即过程TestCalculation,而不是过程TMyForm.tesculation
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的最低版本——就像任何提供的答案都应该兼容的最低特性库一样。给我两分钱。