C# 以异步方式调用同步方法?
我正在开发一个ASP.NET MVC WebApi项目,其中一个方法需要进行LDAP搜索。搜索从LDAP服务器检索的信息量确保调用至少需要7秒才能完成。调用使用System.DirectoryServices.Protocols类和方法时是同步的,不可修改 尽管API位于内部网络中,但该API将接收的通信量相当大,因此每次调用LDAP服务器7秒不是一个好主意。所以我想知道: 用一个异步方法包装它是一个好主意吗? 异步调用的正确方法是什么?wait Task.Run=>Searchparams是可以接受的方式吗?C# 以异步方式调用同步方法?,c#,asp.net-web-api,async-await,ldap-query,C#,Asp.net Web Api,Async Await,Ldap Query,我正在开发一个ASP.NET MVC WebApi项目,其中一个方法需要进行LDAP搜索。搜索从LDAP服务器检索的信息量确保调用至少需要7秒才能完成。调用使用System.DirectoryServices.Protocols类和方法时是同步的,不可修改 尽管API位于内部网络中,但该API将接收的通信量相当大,因此每次调用LDAP服务器7秒不是一个好主意。所以我想知道: 用一个异步方法包装它是一个好主意吗? 异步调用的正确方法是什么?wait Task.Run=>Searchparams是可
正如评论中提到的,我不认为异步调用有什么帮助。在另一个线程中运行它,并按照您的“正确方式”等待。。。这个问题使用了和同步呼叫和等待一样多的资源 但是,请注意,System.DirectoryServices.Protocols类(如LdapCollection)对较旧的APM异步编程模型样式(如/)具有异步支持
通过使用,您可以轻松地将APM样式的API包装为可等待的基于任务的样式,这将是将这些类与异步一起使用的正确方法。另请参见。如评论中所述,我不认为异步调用有什么帮助。在另一个线程中运行它,并按照您的“正确方式”等待。。。这个问题使用了和同步呼叫和等待一样多的资源 但是,请注意,System.DirectoryServices.Protocols类(如LdapCollection)对较旧的APM异步编程模型样式(如/)具有异步支持
通过使用,您可以轻松地将APM样式的API包装为可等待的基于任务的样式,这将是将这些类与异步一起使用的正确方法。另请参见。PD:根据Lucero的回答,这里有一个扩展方法,它隐藏APM调用并将自身公开为常规任务异步方法:
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的对象以基于任务的方式运行。PD:根据Lucero的回答,这里有一个扩展方法,它隐藏APM调用并将自身公开为常规任务异步方法:
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的对象以基于任务的方式运行。Task.Run在ASP.Net MVC中不是一个好主意。每个请求都是它自己的线程,因此无论如何你不会得到任何东西。如果搜索需要7秒,也许你应该每天将所需的完整数据同步到你自己的数据库中一次左右。使调用异步不会加快客户机的响应时间,它可能只会减少服务器上被阻止线程的数量。因此,如果这7秒有问题,您需要整体更改流程,可能是部分LDAP结果或类似结果。在ASP.Net MVC中,Task.Run不是一个好主意。每个请求都是它自己的线程,因此无论如何你不会得到任何东西。如果搜索需要7秒,也许你应该每天将所需的完整数据同步到你自己的数据库中一次左右。使调用异步不会加快客户机的响应时间,它可能只会减少服务器上被阻止线程的数量。因此,如果这7秒有问题,您需要整体更改流程,可能是部分LDAP结果或类似结果。使用您的建议以异步方式重新实现该方法,它工作得非常完美。当然,正如您所说,速度并没有真正的提高,但当我被告知我可以丢弃大部分请求的数据调整查询以仅检索所需的数据时,这就解决了。将执行时间减少到3秒以下,后续查询似乎被缓存。@Léster感谢您的反馈,很高兴知道我的回答有所帮助使用您的建议以异步方式重新实现该方法,它工作得完美无缺。当然,正如您所说,速度并没有真正的提高,但当我被告知我可以丢弃大部分请求的数据调整查询以仅检索所需的数据时,这就解决了。将执行时间减少到3秒以下,后续查询似乎被缓存。@Léster感谢您的反馈,很高兴知道我的回答有所帮助