私は、他のいくつかの Web サービスを順番に呼び出している WCF サービスを持っています。サービスは優先順に並べられますが、並行して呼び出されます。各サービスは 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;
上記のコードは私のコードの非常に単純化されたバージョンですが、基本的には各応答をチェックして、現在最も優先されるサービスであるかどうかを確認します。その場合、ループをキャンセルします。
ただし...この方法でループをキャンセルすると、ループを終了する前に、既に呼び出されたサービスが終了するのを待ちます。いずれかのサービスがタイムアウトになる可能性は十分にありますが、もちろんこれは否定的なものとして扱われます。そのうちの 1 つでもタイムアウトになると、応答時間が 10 秒長くなります。
私がやりたいことは、次のいずれかです。
- 優先サービスをクライアントに返し、すでに開始されているサービスからの応答の処理を続行します (これは、これらのサービスの正/負の割合を知るための純粋なログ記録のためです)。
- ループを即座にキャンセルし、残りの応答を忘れます。理想的には、これを行いたくありません。これは、肯定的に応答したサービスがそのように記録されず、好みの評価に影響することを意味するためです。
だから私の質問はこれです:
私が達成したいことは可能ですか?私は、parallel.foreach がこの仕事に最適なツールではないかもしれないこと、またはクライアントに応答した後に応答をログに記録できないかもしれないことを認識しています。最も重要な要件は、「勝者」がすでに選択されている場合に、サービスが応答するのを待たずに、クライアントが迅速な応答を受信することです。