我有一个 WCF 服务,它依次调用其他几个 Web 服务。这些服务按优先顺序排序,但并行调用。每个服务都会以 true 或 false 进行响应,当所有响应都收到后,最喜欢的肯定会返回给客户端。
但是,在此期间的任何时候,最喜欢的服务都可能会做出积极的回应。此时继续查询其他服务没有意义,所以我希望取消执行并将结果返回给客户端。
我能做的就这么多:
// Use parallelOptions to store the cancellation token
ParallelOptions po = new ParallelOptions();
po.CancellationToken = cts.Token;
Parallel.ForEach<IntegrationObj>(externalServices, po, x =>
{
try
{
// Send requests
SendExternalRequest(x);
po.CancellationToken.ThrowIfCancellationRequested();
}
catch (OperationCanceledException e)
{
/// Don't throw an exception if the loop was cancelled
}
catch (Exception e)
{
LogError(e.Message);
}
});
if (positiveResponses.Count > 0) {
// Get the most preferred positive response and send it back to the client
res = positiveResponses.Where(
x => x.ID == PreferredServiceID)
.FirstOrDefault();
}
return res;
上面的代码是我的代码的一个非常简化的版本,但本质上它会检查每个响应以查看它是否是当前最受欢迎的服务。如果是这样,它会取消循环。
但是...以这种方式取消循环将等待已经调用的任何服务在终止循环之前完成。任何服务都有可能超时,这当然被视为否定。如果只是其中一个超时,它会在我的响应时间上增加 10 秒。
我想做的是以下之一:
- 将首选服务返回给客户端,然后继续处理来自已经启动的服务的响应(这纯粹是为了记录目的,以便我知道这些服务的正/负率)。
- 立即取消循环并忘记剩余的响应。理想情况下,我不想这样做,因为这意味着将不会记录本应积极响应的服务,这将影响他们的偏好评级。
所以我的问题是:
我想要实现的目标可能吗?我意识到 parallel.foreach 可能不是这项工作的最佳工具,或者我可能无法在响应客户端后记录响应。最重要的要求是当“赢家”已经被选中时,客户端无需等待服务响应即可收到快速响应。