【问题标题】:Calling a synchronous method in an async fashion? [duplicate]以异步方式调用同步方法? [复制]
【发布时间】:2019-05-26 08:44:45
【问题描述】:

我正在开发一个 ASP.NET MVC WebApi 项目,其中一种方法需要进行 LDAP 搜索。搜索从 LDAP 服务器检索到的信息量确保调用至少需要 7 秒才能完成。该调用使用System.DirectoryServices.Protocols 类和方法,因此是同步且不可修改的。

此 API 将接收的流量相当大(即使 API 在内部网络中),因此每次调用 LDAP 服务器 7 秒并不是一个好主意。所以我想知道这个:

  • 将其包装在异步方法中是个好主意吗?
  • 异步调用的正确方法是什么? (await Task.Run(() => Search(params)) 是一种可接受的方式吗?)

【问题讨论】:

  • Task.Run 在 ASP.Net MVC 中不是一个好主意。每个请求都是它自己的线程,所以无论如何你都不会得到任何东西。
  • 如果搜索需要7s,也许您应该每天一次左右将您需要的完整数据同步到您自己的数据库中。而不是查询。
  • 使调用异步不会加快客户端的响应时间,它只会(可能)减少服务器上阻塞的线程数量。因此,如果 7 秒有问题,您需要整体更改流程,可能会使用部分 LDAP 结果或类似结果。

标签: c# asp.net-web-api async-await ldap-query


【解决方案1】:

PD:根据 Lucero 的回答,这是一个隐藏 APM 调用并将自身暴露为常规 Task<T> 异步方法的扩展方法:

public static async Task<DirectoryResponse> SendRequestAsync(this LdapConnection conn, string target, string filter,
    SearchScope searchScope, params string[] attributeList)
{
    if (conn == null)
    {
        throw new NullReferenceException();
    }
    var search_request = new SearchRequest(target, filter, searchScope, attributeList);
    var response = await Task<DirectoryResponse>.Factory.FromAsync(
        conn.BeginSendRequest,
        (iar) => conn.EndSendRequest(iar),
        search_request,
        PartialResultProcessing.NoPartialResultSupport,
        null);
    return response;
}

这也可以用作您自己需要的起点(您可以使用类似的方法来“使”支持 APM 的对象以基于任务的样式运行)。

【讨论】:

    【解决方案2】:

    正如评论中所指出的,我完全看不出使调用异步有什么帮助。在另一个线程中运行它并等待(根据您的“什么是正确的方法......”问题)确实使用与同步调用和等待一样多的资源。

    但请注意,System.DirectoryServices.Protocols 类(例如 LdapCollection)确实具有与旧 APM(异步编程模型)样式(例如 BeginSendRequest/EndSendRequest)的异步支持。

    您可以使用TaskFactory&lt;TResult&gt;.FromAsync 轻松地将 APM 样式的 API 包装为可等待的基于任务的样式,这是将这些类与异步一起使用的“正确方式”。另见Interop with Other Asynchronous Patterns and Types

    【讨论】:

    • 使用您的建议以异步方式重新实现该方法,它完美地工作。当然,正如您所说,速度并没有真正的提高,但是当我被告知我可以丢弃大部分请求的数据时,问题就解决了(调整查询以仅检索需要的数据将执行时间减少到 3 位以下秒和后续查询似乎被缓存)。
    • @Léster 感谢您的反馈,很高兴知道我的回复有所帮助。 :)
    猜你喜欢
    • 1970-01-01
    • 2011-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-19
    • 2017-09-23
    相关资源
    最近更新 更多