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

标签 c# asynchronous restsharp

在处理使用异步 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 a Return (Visual Basic) or return (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 来执行此操作的方法关键字,它知道如何处理 TaskTask<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/

相关文章:

c# - 在 C# 中反序列化嵌套 JSON 数组时出现问题

c# - RestSharp 忽略 .NET Core 上的系统代理(例如 Fiddler)

c# - 在调试器中查看 C# 泛型的类型

javascript - 尝试从 JSON 文件返回 URL

c# - 如何在 ASP.NET 中的运行状况检查返回 'degraded'/'unhealthy' 时发送电子邮件警报

c# - 等待期间多个任务的控制流

javascript - ES6 嵌套 Promise

httprequest - RestSharp RestResponse 将内容截断为 64 kb

c# - 实现 IDisposable 时在构造函数中处理异常

c# - 在后台运行 Mono 应用程序时,我可以检测到缺少控制台吗?