简体   繁体   中英

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. The amount of information the search retrieves from the LDAP server ensures the call takes at least 7 seconds to complete. The call, as it uses the System.DirectoryServices.Protocols classes and methods, is synchronous and unmodifiable.

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. 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?)

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 ).

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. 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:

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).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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