C# WCF客户端允许一个操作并行运行,但不允许另一个操作并行运行?
我有一个WCFSOAP客户机,它是从服务WSDL生成的。除其他外,该服务还提供C# WCF客户端允许一个操作并行运行,但不允许另一个操作并行运行?,c#,multithreading,wcf-client,C#,Multithreading,Wcf Client,我有一个WCFSOAP客户机,它是从服务WSDL生成的。除其他外,该服务还提供查询和批处理操作。它还声称提供多线程请求处理 在尝试并行使用我的客户机时,我看到了一个奇怪的行为:客户机会很高兴地发送我告诉它的并行查询请求,但一次只发送一个批处理请求。我使用Fiddler来观察流量,我可以看到10个打开的查询请求,但是批处理请求总是一次启动和完成一个 我正在对两个代码路径使用Parallel.ForEach,并将maxdegreeofpparallelism设置为10。我没有更改ServicePoi
查询
和批处理
操作。它还声称提供多线程请求处理
在尝试并行使用我的客户机时,我看到了一个奇怪的行为:客户机会很高兴地发送我告诉它的并行查询
请求,但一次只发送一个批处理
请求。我使用Fiddler来观察流量,我可以看到10个打开的查询
请求,但是批处理
请求总是一次启动和完成一个
我正在对两个代码路径使用Parallel.ForEach
,并将maxdegreeofpparallelism
设置为10。我没有更改ServicePointManager.DefaultConnectionLimit
,不过我注意到,如果我将其设置为小于线程数,则查询
请求将受到限制。通过查看并行执行路径中的ManagedThreadId
值,我已经验证了TPL正在加速多个线程
据我所知,与客户观点的唯一区别是query
使用HTTPGET
方法,batch
使用POST
方法。这会导致我看到的行为吗?还有什么我可以看的吗
按要求编辑以下是相关的客户端代码(我已删除了ServiceKnownType
属性)
EDIT2
这是我的调试输出,试图跟踪它
Creating…{Thread Id}
在我开始为batch
操作准备有效负载之前立即写入控制台
Sending…{Thread Id}
行在调用batch
操作之前立即写入控制台
Sent…{Thread Id}
批处理操作完成后,立即将行写入控制台
以下是此次跑步的Fiddler日志:
以下是Fiddler日志中关于查询
代码路径的剪报,仅供参考:
您是否控制服务?该服务可以设置为一次只处理一个呼叫。请参阅Juval的《编程WCF服务》一书中的第8章。@EricScherrer否-该服务由第三方提供。即使服务正在节流,如果客户端发出多个并发请求,我仍然希望看到连接请求在Fiddler中等待。您可以发布生成的客户端吗?不知道该方法是否有任何有趣的属性。@EricScherrer我用该代码更新了问题。类方法中没有属性,但我在接口方法中包含了除
ServiceKnownType
属性之外的所有属性。我不确定您对待这两个方法的方式是否真的没有区别。尝试创建一段最小的代码来重现这一点。只需调用Parallel.ForEach,使用一个组成的工作负载和一个调用服务的单行主体。把代码贴在这里。
//generated client interface
//{...
[OperationContract(Action = "", ReplyAction = "*")]
[FaultContract(typeof (fault), Action = "", Name = "fault")]
[XmlSerializerFormat(SupportFaults = true)]
[return: MessageParameter(Name = "return")]
QueryResponse query(QueryRequest queryRequest);
[OperationContract(Action = "", ReplyAction = "*")]
[FaultContract(typeof (fault), Action = "", Name = "fault")]
[XmlSerializerFormat(SupportFaults = true)]
[return: MessageParameter(Name = "return")]
BatchResponse batch(BatchRequest batchRequest);
//...}
//generated client class
//{...
public QueryResponse query(QueryRequest queryRequest)
{
return this.Channel.query(queryRequest);
}
public BatchResponse batch(BatchRequest batchRequest)
{
return this.Channel.batch(batchRequest);
}
//...}
1:53:58 PM (Thread 4)
1:53:58 PM (Thread 19)
1:53:58 PM (Thread 20)
1:53:58 PM (Thread 16)
1:53:58 PM (Thread 18)
1:53:58 PM (Thread 17)
1:53:58 PM (Thread 7)
1:53:58 PM (Thread 15)
Creating...19
Creating...15
Creating...16
Creating...17
Creating...7
Creating...4
Creating...20
Creating...18
Sending...17
Sending...7
Sending...20
Sending...19
Sending...16
Sending...18
Sending...4
Sending...15
1:53:59 PM (Thread 22)
Creating...22
Sending...22
1:53:59 PM (Thread 23)
Creating...23
Sending...23
Sent...17
Sent...15
Sent...7
Sent...18
Sent...20
Sent...16
Sent...4
Sent...19
Sent...22
Sent...23