在处理使用异步 rest 调用的数据 API 时(我使用的是 RestSharp.Portable),处理返回值的最佳方式是什么?由于 async 函数只能返回一个 Task 或 Task ...但调用方无法返回返回值 ...API 如何将数据返回给调用方?全局属性?
从我目前所读的内容来看,回调函数似乎是与响应数据交互的唯一方式?
以下面的方法为例;以前我没有使用异步 Rest 库并且能够返回一个值但是在将它转换为使用 RestSharp.Portable 之后,我看不到返回值的方法:
public async Task<EntityResourceDescriptor> GetEntityDescriptor(string entityType)
{
TaskCompletionSource<EntityResourceDescriptor> tcs = new TaskCompletionSource<EntityResourceDescriptor>();
var req = new RestRequest("/qcbin/rest/domains/{domain}/projects/{project}/customization/entities/{entityType}");
AddDomainAndProject(req);
req.AddParameter("entityType", entityType, ParameterType.UrlSegment);
client.ExecuteAsync<EntityResourceDescriptor>(req, (res) =>
{
if (res.ResponseStatus == ResponseStatus.Error)
{
tcs.TrySetException(res.ErrorException);
}
else
{
tcs.SetResult(res.Data);
}
}
);
return tcs.Task;
}
在这里,我所能做的就是返回任务,但调用者仍然无法获取响应数据,或者我是否遗漏了一些明显的东西?调用者可以订阅在 Task.Completed 等处触发的事件吗?
我对这个异步概念很模糊。是否有任何编写可移植数据 API 的示例?
最佳答案
我认为您真的需要退后一步,阅读有关如何使用 async
的信息。和 await
关键字。除其他事项外,您还需要了解编码时在幕后发生的一些编译器魔法 async
方法。
这是一个很好的起点:Asynchronous Programming with Async and Await .
关于您的问题,Return Types and Parameters部分是这样说的:
You specify
Task<TResult>
as the return type if the method contains aReturn
(Visual Basic) orreturn
(C#) statement that specifies an operand of type TResult.
然后给出如下代码示例:
// Signature specifies Task<TResult>
async Task<int> TaskOfTResult_MethodAsync()
{
int hours;
// . . .
// Return statement specifies an integer result.
return hours;
}
请注意尽管方法返回类型为 Task<int>
, return
语句只返回 int
, 不是 Task<int>
.这基本上是因为有一些编译器在运行,使得这只在 async
中合法。方法。
不想深入了解所有细节,您还应该知道 async
的调用者通常期望使用 await
来执行此操作的方法关键字,它知道如何处理 Task
或 Task<TResult>
返回值并以透明的方式自动为您解包实际的预期返回值(幕后有更多的编译器魔法)。
所以对于上面的例子,这里有一种调用方式:
int intValue = await TaskOfTResult_MethodAsync(); // Task<int> is automatically unwrapped to an int by the await keyword when the async method completes.
或者,如果您希望启动异步方法,同时执行一些其他工作,然后等待异步方法完成,可以这样做:
Task<int> t = TaskOfTResult_MethodAsync();
// perform other work here
int intValue = await t; // wait for TaskOfTResult_MethodAsync to complete before continuing.
希望这能让您大致了解如何从异步方法传回值。
对于您的具体示例,我不熟悉 RestSharp(从未使用过)。但是从我阅读的内容来看,我认为你会想要使用 client.ExecuteTaskAsync<T>(request)
而不是 client.ExecuteAsync<T>(request, callback)
更好地适应 async-await
模型。
我认为您的方法应该看起来像这样:
public async Task<EntityResourceDescriptor> GetEntityDescriptor(string entityType)
{
var req = new RestRequest("/qcbin/rest/domains/{domain}/projects/{project}/customization/entities/{entityType}");
AddDomainAndProject(req);
req.AddParameter("entityType", entityType, ParameterType.UrlSegment);
var res = await client.ExecuteTaskAsync<EntityResourceDescriptor>(req);
if (res.ResponseStatus == ResponseStatus.Error)
{
throw new Exception("rethrowing", res.ErrorException);
}
else
{
return res.Data;
}
}
您的调用代码将如下所示:
EntityResourceDescriptor erd = await GetEntityDescriptor("entityType");
我希望你能成功。但同样,请务必阅读有关 async-await
的文档编程风格。一旦您全神贯注于为您完成的编译器魔术,它就会非常整洁。但是,如果您不花时间真正了解它的工作原理,就很容易迷路。
关于c# - 如何处理异步函数中的返回值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31496755/