[英]Call synchronous webservice methods asynchronously
我必须每次用不同的参数循环调用一个Web服务方法约一百次。 该Web服务只有同步方法。 目前,我正在控制台应用程序中对此进行测试,同步进行数据需要花费十分钟以上的时间!
我想要的是:并行运行10个请求。 完成后,执行接下来的十个调用。 这当然应该是异步的。
该功能将托管在IIS托管的wcf服务中。
概述:客户端一次使用参数调用wcf服务。 wcf服务方法应异步调用另一个Web服务一百次,并将最终数据保存到Excel。
我读到,在Web应用程序中使用Task.Run并不是一个好主意。
那么,如何在Web上下文中异步调用同步Web服务方法?
我正在使用CRM Microsoft.Xrm.Sdk ,版本= 7.0.0.0,区域性=中性,PublicKeyToken = 31bf3856ad364e35
var orders = _serviceProxy.RetrieveMultiple( new FetchExpression(strXmlFetch));
RetrieveMultiple获取一个XML片段(strXmlFetch),在其中定义查询并执行请求。 该方法位于此处:
命名空间 Microsoft.Xrm.Sdk.Client
类 OrganizationServiceProxy
public EntityCollection RetrieveMultiple(QueryBase query);
在后台,客户端SDk在调用RetrieveMultiple时会执行以下操作。
using (OrganizationServiceContextInitializer organizationServiceContextInitializer = new OrganizationServiceContextInitializer(this))
{
entityCollection = base.ServiceChannel.Channel.RetrieveMultiple(query);
return entityCollection;
}
我还没有实现任何东西,因为我需要一个异步执行请求的起点。
该Web服务只有同步方法
默认情况下,Web服务会生成与BeginXX, EndXX
有关的Asynchronous
方法,它们是Asynchronous Programming Model
一部分,但不是Async-Await
可以使用的方法,因为它们不返回Task
。
我想要的是:并行运行10个请求。 完成后,执行接下来的十个调用。 这当然应该是异步的。
在真正的Async
调用中,因为没有threads
被调用并且可以在IO完成端口上工作,因此您可以启动的调用数量比10个更多。否则,一次调度10个异步请求的逻辑必须自定义,这是不可能的。盒机制可以做到这一点,即使在使用Threadpool
,也不能保证并行请求的数量,尽管您可以将Max Degree of Parallelism
设置为对Parallel API更高的限制。
概述:客户端一次使用参数调用wcf服务。 wcf服务方法应异步调用另一个Web服务一百次,并将最终数据保存到Excel。
您可能希望所有调用都是异步的,这样无论Ucf线程对wcf服务还是Web服务都不会被阻止。
我读到
Task.Run
在Web应用程序中使用时不是一个好主意。
的确,由于正在调用ThreadPool
线程,因此在将IO
调用分派到Web Service
后,将不会执行任何操作
那么,如何在Web上下文中异步调用同步Web服务方法?
需要通过Sync方法进行异步包装,该方法是“反模式”,但是没有其他选择。 这将需要一个ThreadPool
线程,例如:
public class AsyncWrapper
{
public async Task CallWcfAsync(<Parameters>)
{
SynchronizationContext _synchronizationContext =
SynchronizationContext.Current;
try
{
SynchronizationContext.SetSynchronizationContext(null);
await Task.Run(() => CallWcfMethod(<Parameters>));
}
finally
{
SynchronizationContext.SetSynchronizationContext
(_synchronizationContext);
}
}
}
重要事项:
CallWcfAsync
是您需要的Async wrapper method
。
注意,我在执行之前将Synchronization上下文设置为Null
,然后将其重置,这在行为上与ConfigureAwait(false)
类似,否则在Web应用程序中,这将导致死锁,因为等待的Sychronization Context
被阻止。
这当然应该是异步的。
好吧,那将是理想的。 但是, OrganizationServiceProxy
没有异步方法 ( IOrganizationService
也没有 ,因此直接使用ServiceChannel.Channel
也无济于事)。
因此,要做的第一件事是要求Microsoft将异步API添加到该客户端库。
我读到,在Web应用程序中使用Task.Run并不是一个好主意。
通常情况是对的。 您想调用异步API。 在这种情况下不可用。
那么,如何在Web上下文中异步调用同步Web服务方法?
这是不可能的。 您的选择是:
服务器端并行处理的问题在于,您现在对单个请求使用N
线程,这确实可以使您的Web服务器迅速崩溃。 我不建议在生产代码中使用这种方法,特别是如果它是通过Internet公开的。
但是,如果确定对WCF服务的调用不会太多,则可以并行实现它。
由于您需要从并行查询中收集结果,因此建议您使用Parallel LINQ ( AsParallel
)指定WithDegreeOfParallelism(10)
,例如:
IEnumerable<EntityCollection> GetAll(OrganizationServiceProxy proxy, IEnumerable<QueryBase> queries)
{
return queries.AsParallel().WithDegreeOfParallelism(10)
.Select(query => proxy.RetrieveMultiple(query));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.