如何处理异步函数中的返回值

在处理使用异步rest调用的数据API时(我使用的是RestSharp.Portable),处理返回值的最佳方法是什么? 由于异步函数只能返回任务或任务…但调用者无法返回返回值… API如何将数据返回给调用者? 全球物业?

从我到目前为止所看到的,似乎回调函数是与Response Data交互的唯一方法?

以下面的方法为例; 以前我没有使用异步Rest库并且能够返回一个值但是在将其转换为使用RestSharp.Portable后,我没有看到返回值的方法:

public async Task GetEntityDescriptor(string entityType) { TaskCompletionSource tcs = new TaskCompletionSource(); var req = new RestRequest("/qcbin/rest/domains/{domain}/projects/{project}/customization/entities/{entityType}"); AddDomainAndProject(req); req.AddParameter("entityType", entityType, ParameterType.UrlSegment); client.ExecuteAsync(req, (res) => { if (res.ResponseStatus == ResponseStatus.Error) { tcs.TrySetException(res.ErrorException); } else { tcs.SetResult(res.Data); } } ); return tcs.Task; } 

我所能做的就是返回Task,但是调用者仍无法获取响应数据,或者我错过了一些明显的东西? 调用者是否可以订阅在Task.Completed等处被触发的事件?

我对这个异步概念非常模糊。 是否有编写可移植数据API的示例?

我认为你真的需要退后一步,阅读有关如何使用asyncawait关键字的信息。 除此之外,您还需要了解编码async方法时幕后发生的一些编译器魔法。

这是一个很好的起点: 使用Async和Await进行异步编程 。

更多问题, 返回类型和参数部分有这样的说法:

如果方法包含指定TResult类型的操作数的Return (Visual Basic)或return (C#)语句,则指定Task作为返回类型。

然后给出以下代码示例:

 // Signature specifies Task async Task TaskOfTResult_MethodAsync() { int hours; // . . . // Return statement specifies an integer result. return hours; } 

请注意,尽管返回类型为Task ,但return语句只返回一个int ,而不是一个Task 。 这基本上是因为有一些编译器魔法正在进行,这使得这只在async方法中合法。

在不想了解所有细节的情况下,您还应该知道async方法的调用者通常希望使用await关键字,它知道如何处理TaskTask返回值并自动解包以透明的方式为您提供实际预期的返回值(幕后更多的编译魔术)。

所以对于上面的例子,这里有一种方法来调用它:

 int intValue = await TaskOfTResult_MethodAsync(); // Task is automatically unwrapped to an int by the await keyword when the async method completes. 

或者,如果您希望启动异步方法,在此期间执行其他一些工作,然后等待异步方法完成,可以这样做:

 Task t = TaskOfTResult_MethodAsync(); // perform other work here int intValue = await t; // wait for TaskOfTResult_MethodAsync to complete before continuing. 

希望这能让您大致了解如何从异步方法传递值。

对于您的具体示例,我不熟悉RestSharp(从未使用过它)。 但是从我读的很少,我想你会想要使用client.ExecuteTaskAsync(request)而不是client.ExecuteAsync(request, callback)来更好地适应async-await模型。

我在想你的方法看起来像这样:

 public async Task 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(req); if (res.ResponseStatus == ResponseStatus.Error) { throw new Exception("rethrowing", res.ErrorException); } else { return res.Data; } } 

您的调用代码将如下所示:

 EntityResourceDescriptor erd = await GetEntityDescriptor("entityType"); 

我希望你设法让这个工作。 但同样,请务必阅读有关async-await编程风格的文档。 一旦你围绕为你完成的编译器魔法包裹你的头部,它就非常整洁。 但如果你没有花时间真正理解它是如何工作的,那么它很容易迷失。