以异步方式调用同步方法吗?

时间:2018-12-28 14:22:03

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

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

此API接收的流量非常大(即使该API位于内部网络中),因此对LDAP服务器的每次调用都需要7秒。所以我想知道这一点:

  • 将其包装在异步方法中是个好主意吗?
  • 异步执行此呼叫的正确方法是什么? (await Task.Run(() => Search(params))可以接受吗?)

2 个答案:

答案 0 :(得分:4)

如评论中所述,我完全看不到使调用异步将如何有所帮助。在另一个线程中运行它并等待(按照您的“什么是正确的方法……”问题)确实消耗了与同步调用和等待一样多的资源。

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

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

答案 1 :(得分:0)

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的对象以基于任务的样式运行)。