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 与FireMonkey并行的多个REST请求_Multithreading_Delphi_Rest_Asynchronous - Fatal编程技术网

Multithreading 与FireMonkey并行的多个REST请求

Multithreading 与FireMonkey并行的多个REST请求,multithreading,delphi,rest,asynchronous,Multithreading,Delphi,Rest,Asynchronous,我正在Rad Studio XE7中构建一个Firemonkey应用程序,在这里单击一个按钮,我将需要使用TRestRequest进行多个(大约7个)web服务调用。每个web服务都将返回json对象,然后该对象将填充数据集。 我正在寻找一种方法来同时调用这些调用,而不必锁定应用程序的UI 你建议用哪种方法来做这件事?我看到Embarcadero为线程引入了新的任务和特性功能,但我仍然不确定我们是否可以使用它以及如何使用它。另外,我看到有一个函数可以使用以下函数异步执行TRestRequest:

我正在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;
但是我找不到任何关于如何使用这种方法及其作用的文档

任何输入都将不胜感激。

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

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

ExecuteAsync方法在
REST.Client
中定义。(我有Delphi XE-10.1.Berlin,所以它有一个额外的参数,
accompletionHandlerWitherRor
——在出错时调用。不过原理保持不变)

我们来看看,

函数TCustomRESTRequest.ExecuteAsync(accompletionHandler:tccompletionHandler=nil;异步化:boolean=true;
AFreeThread:boolean=true;ACompletionHandlerWithError:TCompletionHandlerWithError=nil):树执行读取;
开始
结果:=TRESTExecutionThread.Create(Execute、self、accompletionhandler、asynchronoused、AFreeThread、accompletionhandlerwitherror);
结束;
这里发生的是创建一个新线程,在其中执行REST请求。如果响应传入,则由
ACompletionHandler
处理
默认情况下,
ACompletionHandler
在由
ExecuteAsync
创建的新线程上运行。如果希望它在主线程上运行,则应将
异步化
设置为

但是您如何访问该响应,并使程序的其余部分可以访问它?

FireMonkey的TRESTRequest类有一个属性
Response
,该属性指向包含服务器对我们请求的响应的TRESTResponse对象。
不幸的是,TresRequest和TresResponse对象都没有传递给我们的CompletionHandler

因此,我们需要以某种方式向CompletionHandler提供这些信息。幸运的是,我们可以将方法用作CompletionHandler

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

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

类型TDataOwner=class
MyData:TSomeDataType;
过程GetData();
过程FillDataSet();
结束;
实施
过程DataOwner.GetData();
开始
// ... 在此处初始化MyRESTRequest。。。
MyRESTRequest.ExecuteAsync(FillDataSet);
结束;
过程DataOwner.FillDataSet();
开始
MyData:=processResponse(MyRESTRequest.Response);
结束;

如果您想并行触发多个请求,则需要多次使用此模式。不幸的是,我们不能在完成处理程序中直接访问TRESTRequest实例或TRESTResponse实例,因为这意味着我们必须自己记账。换句话说,由程序员来确保完成处理程序处理正确的响应对象

@jerrydoge不表示它不会阻止?最终,异步操作将终止,应用程序可以对结果进行处理。@mjn单击此按钮,我们将调用这7个web服务,实际上会打开一个多视图,在本例中,该视图将包含一组筛选组合框,这些组合框将通过从web服务获取数据来填充。我的想法是让用户能够真正取消过滤,只需触摸multiview之外的区域,即可关闭multiview而不应用任何过滤器。多个并行请求的想法是,如果我们并行发送7个请求,而不是一次发送一个请求,那么这7个组合框的填充速度会更快。@Jerrydoge您应该在后台执行所有长时间(er)运行的任务,以防止UI线程阻塞。这不仅适用于用户,而且操作系统也在寻找没有响应的应用程序。@JerryDodge f.i.Android会在应用程序因为没有响应而被冻结时弹出一个对话框。因此,必须这样做。对不起,我不明白你为什么要问。在我看来,这就像是在问“你为什么不想开车穿过邻居的花园?”:o)@jerrydoge这肯定是正确的选择——没有任何可接受的良好工作选项