与FireMonkey并行的多个REST请求

时间:2014-12-03 18:46:56

标签: multithreading delphi rest asynchronous

我在Rad Studio XE7中构建Firemonkey应用程序,只需单击一下按钮,我就需要使用TRestRequest进行多次(大约7次)Web服务调用。每个Web服务都将返回json对象,然后填充数据集。 我正在寻找同时进行这些调用的方法,而不是要锁定应用程序的UI。

您建议以哪种方式执行此操作?我看到Embarcadero为线程引入了新的任务和功能,但我仍然不确定我们是否可以使用它以及如何使用。另外,我看到有一个函数可以使用这个函数异步执行TRestRequest:

function TCustomRESTRequest.ExecuteAsync(ACompletionHandler: TCompletionHandler = nil; ASynchronized: boolean = true; AFreeThread: boolean = true): TRESTExecutionThread;

但我无法找到有关如何使用此方法及其功能的任何文档。

非常感谢任何输入。

1 个答案:

答案 0 :(得分:2)

ExecuteAsync(ACompletionHandler: TCompletionHandler = nil; ASynchronized: boolean = true; AFreeThread: boolean = true)方法确实是要走的路。顾名思义,它是异步的;这意味着你的程序在发出请求后仍然保持响应,甚至在发出多个请求之后 但是,从不同的对象实例中激发这些不同的请求非常重要;如果您从已执行ExecuteAsync的{​​{1}}实例触发TRESTRequest,则新请求将妨碍现有请求。您必须为每个并行调用创建单独的ExecuteAsync实例。

请注意,它的第一个参数是一个过程;您将所选的过程作为该参数传递。唯一的要求是该程序具有正确的签名;在这种情况下,它是一个没有参数的过程。

ExecuteAsync方法在TRESTRequest中定义。 (我已经得到了Delphi XE-10.1。柏林所以它有一个额外的参数,REST.Client - 在出错时被调用。但原理仍然是相同的。)

让我们来看看:

ACompletionHandlerWithError

这里发生的是创建一个新的线程,在该线程中执行REST请求。如果响应进来,则由function TCustomRESTRequest.ExecuteAsync(ACompletionHandler: TCompletionHandler = nil; ASynchronized: boolean = true; AFreeThread: boolean = true; ACompletionHandlerWithError: TCompletionHandlerWithError = nil): TRESTExecutionThread; begin Result := TRESTExecutionThread.Create(Execute, self, ACompletionHandler, ASynchronized, AFreeThread, ACompletionHandlerWithError); end; 处理 默认情况下,ACompletionHandlerACompletionHandler创建的新线程上运行。如果您希望它在主线程上运行,则应将ExecuteAsync设置为ASynchronized

但是,您如何才能访问该回复,并让其他程序可以访问该回复?

FireMonkey的TRESTRequest类有一个属性true,它引用包含服务器对我们请求的响应的TRESTResponse对象。
不幸的是,TRESTRequest和TRESTResponse对象都没有传递给我们的CompletionHandler!

所以我们需要以某种方式给CompletionHandler这个信息。幸运的是,我们可以将方法用作CompletionHandler。

假设要处理结果数据的类称为Response。我们的目的是DataOwner可以访问与TRESTRequest实例关联的TRESTResponse实例。
最简单的方法是使TRESTRequest和/或TRESTResponse成为DataOwner的成员。

假设您的请求是从名为DataOwner的TRESTRequest实例触发并由函数MyRESTRequest处理的,您将使用以下代码:

processResponse

如果要并行触发多个请求,则需要多次使用此模式。遗憾的是,我们没有直接访问完成处理程序中的TRESTRequest实例或TRESTResponse实例,因为这意味着我们必须自己进行簿记。换句话说,程序员需要确保Completion Handler处理正确的Response对象。