以异步方式调用同步方法?
Calling a synchronous method in an async fashion?
我正在开发一个 ASP.NET MVC WebApi 项目,其中一种方法需要进行 LDAP 搜索。搜索从 LDAP 服务器检索的信息量确保调用至少需要 7 秒才能完成。该调用使用 System.DirectoryServices.Protocols
类 和方法,是同步且不可修改的。
此 API 将接收的流量相当大(即使 API 在内部网络中)因此每次调用 LDAP 服务器 7 秒不是一个好主意.所以我想知道这个:
- 用异步方法包装它是个好主意吗?
- 异步调用的正确方法是什么? (
await Task.Run(() => Search(params))
是一种可接受的方式吗?)
如评论中所述,我完全看不出使调用异步会有什么帮助。 运行 它在另一个线程中等待(根据您的 "what is the proper way..." 问题)确实使用了与同步调用和等待一样多的资源。
但是请注意,System.DirectoryServices.Protocols
类 例如 LdapCollection
确实支持旧的 APM(异步编程模型)样式(例如 BeginSendRequest
/EndSendRequest
) .
您可以使用 TaskFactory<TResult>.FromAsync
, this would be the "proper way" of using these classes with async. See also Interop with Other Asynchronous Patterns and Types.
轻松地将 APM 样式的 API 包装为可等待的基于任务的样式
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;
}
这也可以作为满足您自己需求的起点(您可以使用类似于 "make" APM 支持对象以基于任务的方式运行的方法)。
我正在开发一个 ASP.NET MVC WebApi 项目,其中一种方法需要进行 LDAP 搜索。搜索从 LDAP 服务器检索的信息量确保调用至少需要 7 秒才能完成。该调用使用 System.DirectoryServices.Protocols
类 和方法,是同步且不可修改的。
此 API 将接收的流量相当大(即使 API 在内部网络中)因此每次调用 LDAP 服务器 7 秒不是一个好主意.所以我想知道这个:
- 用异步方法包装它是个好主意吗?
- 异步调用的正确方法是什么? (
await Task.Run(() => Search(params))
是一种可接受的方式吗?)
如评论中所述,我完全看不出使调用异步会有什么帮助。 运行 它在另一个线程中等待(根据您的 "what is the proper way..." 问题)确实使用了与同步调用和等待一样多的资源。
但是请注意,System.DirectoryServices.Protocols
类 例如 LdapCollection
确实支持旧的 APM(异步编程模型)样式(例如 BeginSendRequest
/EndSendRequest
) .
您可以使用 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:根据 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;
}
这也可以作为满足您自己需求的起点(您可以使用类似于 "make" APM 支持对象以基于任务的方式运行的方法)。