C# WCF客户端允许一个操作并行运行,但不允许另一个操作并行运行?

C# WCF客户端允许一个操作并行运行,但不允许另一个操作并行运行?,c#,multithreading,wcf-client,C#,Multithreading,Wcf Client,我有一个WCFSOAP客户机,它是从服务WSDL生成的。除其他外,该服务还提供查询和批处理操作。它还声称提供多线程请求处理 在尝试并行使用我的客户机时,我看到了一个奇怪的行为:客户机会很高兴地发送我告诉它的并行查询请求,但一次只发送一个批处理请求。我使用Fiddler来观察流量,我可以看到10个打开的查询请求,但是批处理请求总是一次启动和完成一个 我正在对两个代码路径使用Parallel.ForEach,并将maxdegreeofpparallelism设置为10。我没有更改ServicePoi

我有一个WCFSOAP客户机,它是从服务WSDL生成的。除其他外,该服务还提供
查询
批处理
操作。它还声称提供多线程请求处理

在尝试并行使用我的客户机时,我看到了一个奇怪的行为:客户机会很高兴地发送我告诉它的并行
查询
请求,但一次只发送一个
批处理
请求。我使用Fiddler来观察流量,我可以看到10个打开的
查询
请求,但是
批处理
请求总是一次启动和完成一个

我正在对两个代码路径使用
Parallel.ForEach
,并将
maxdegreeofpparallelism
设置为10。我没有更改
ServicePointManager.DefaultConnectionLimit
,不过我注意到,如果我将其设置为小于线程数,则
查询
请求将受到限制。通过查看并行执行路径中的
ManagedThreadId
值,我已经验证了TPL正在加速多个线程

据我所知,与客户观点的唯一区别是
query
使用HTTP
GET
方法,
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