4

我有一个WCF服务,该服务又调用其他几个Web服务。这些服务按照优先顺序排列,但并行调用。每项服务都会以真或假做出回应,并且当收到所有回复后,最可取的积极信息将返回给客户。如何在WCF服务中返回值后继续处理

但是,在此期间的任何时候,最喜欢的服务可能会以积极的方式回应。此时继续查询其他服务是没有意义的,所以我希望取消执行并将结果返回给客户端。

这一点我可以这样做:

// 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秒。

我想什么做的是下列之一:

  1. 返回首选服务到客户端,然后继续处理,从已经启动的服务走在了回应(这纯粹是为了记录目的,以便我知道这些服务的积极/消极比率)。
  2. 立即取消循环并忘记其余的响应。理想情况下,我不想这样做,因为这意味着服务可能会有积极回应,不会被记录下来,这会影响他们的偏好等级。

所以我的问题是这样的:

是我想达到什么可能?我意识到parallel.foreach可能不是这项工作的最佳工具,或者我可能无法在回复客户端后记录响应。最重要的要求是客户在获得“胜利者”时无需等待服务响应就能获得快速响应。

回答

1

目前设置的方式是所有的服务都是并行启动的,但您的支票只能在所有服务完成后才会编程。
如果你想坚持你的foreach方法,你可以在foreach中写if条件,这样,如果一个服务首先完成,它将直接执行检查的积极响应,你可以作出相应的反应(返回值/杀死其他人)。
请注意,这种方法有更多的线程不足,您必须注意(从列表中读取某个服务可能正在尝试写入的内容)。也有可能两个服务同时完成,因此您的if语句会激发两次。

foreach方法的一种替代方法是为每个服务创建一个线程,将所有线程放入列表中,并在启动所有线程后立即启动一个while循环,以便继续检查(关闭课程)完成服务。这样,您可以通过中断while循环来返回其他线程仍在运行的值。

+1

我到最后第二种方法。这确实意味着在决定结果后仍然会继续查询剩余的服务,但是已经胜过了Parallel.ForEach。 – Maloric 2012-04-26 14:34:41