简体   繁体   English

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

[英]Calling a synchronous method in an async fashion?

I'm developing an ASP.NET MVC WebApi project and one of the methods needs to make a LDAP search. 我正在开发一个ASP.NET MVC WebApi项目,其中一种方法需要进行LDAP搜索。 The amount of information the search retrieves from the LDAP server ensures the call takes at least 7 seconds to complete. 搜索从LDAP服务器检索到的信息量可确保呼叫至少花费7秒钟才能完成。 The call, as it uses the System.DirectoryServices.Protocols classes and methods, is synchronous and unmodifiable. 该调用使用System.DirectoryServices.Protocols类和方法,因此是同步的且不可修改。

The amount of traffic this API will receive is rather big (even though the API is in an internal network) so 7 seconds for each call to the LDAP server is not a good idea. 该API将接收的流量非常大(即使该API在内部网络中),因此对LDAP服务器的每次调用都需要7秒的时间不是一个好主意。 So I want to know this: 所以我想知道这一点:

  • Is it a good idea to wrap this in an asynchronous method? 将其包装在异步方法中是个好主意吗?
  • What's the proper way to async this call? 同步此呼叫的正确方法是什么? (is await Task.Run(() => Search(params)) an acceptable way?) (正在await Task.Run(() => Search(params))可以接受吗?)

As noted in the comment I don't see how making the call asynchronous would help at all. 如评论中所述,我完全看不到使调用异步将如何帮助您。 Running it in another thread and awaiting (as per your "what is the proper way..." question) does use as many resources as synchronously calling and waiting. 在另一个线程中运行它并等待(按照您的“什么是正确的方法……”问题)确实使用了与同步调用和等待一样多的资源。

Note, however, that the System.DirectoryServices.Protocols classes such as LdapCollection do have async support with the older APM (Asynchronous Programming Model) style (eg BeginSendRequest / EndSendRequest ). 但是请注意,诸如LdapCollection类的System.DirectoryServices.Protocols类确实具有对较早的APM(异步编程模型)样式(例如BeginSendRequest / EndSendRequest )的异步支持。

You can easily wrap APM-style APIs to awaitable Task-based style by using TaskFactory<TResult>.FromAsync , this would be the "proper way" of using these classes with async. 您可以使用TaskFactory<TResult>.FromAsync轻松地将APM样式的API包装为可等待的基于任务的样式,这是将这些类与async一起使用的“正确方法”。 See also Interop with Other Asynchronous Patterns and Types . 另请参见与其他异步模式和类型互操作

PD: Based on Lucero's answer, here's an extension method that hides the APM calls and exposes itself as a regular Task<T> async method: 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;
}

This can also be used as a starting point for your own needs (you can use a similar method to "make" APM-supporting objects behave in Task-based style). 这也可以用作您自己需要的起点(您可以使用类似的方法来“使”支持APM的对象以基于任务的样式运行)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM