私は V2 から WCF で Silverlight を使用しており (現在は V4 で作業しています)、これが私が見つけたものです。一般に、1 つのクライアントを開き、その 1 つのクライアントだけをすべての通信に使用することは非常にうまく機能します。また、DuplexHttBinding を使用していない場合は、反対のことを行って、毎回新しい接続を開き、完了したら閉じることもできます。また、Microsoft が Silverlight で WCF クライアントを設計した方法により、1 つのクライアントを常に開いたままにしておく場合と、要求ごとに新しいクライアントを作成する場合とでは、パフォーマンスに大きな違いは見られません。(ただし、リクエストごとに新しいクライアントを作成している場合は、それも閉じていることを確認してください。)
ここで、DuplexHttBinding を使用している場合、つまりサーバーからクライアントのメソッドを呼び出したい場合は、要求ごとにクライアントを閉じないことがもちろん重要です。それはただの常識です。ただし、どのドキュメントにも記載されていませんが、私が絶対に重要であることがわかったのは、DuplexHttBinding を使用している場合、クライアントのインスタンスを一度に 1 つだけ開く必要があるということです。そうしないと、あらゆる種類の厄介なタイムアウトの問題に遭遇し、トラブルシューティングが非常に困難になります。接続が 1 つあれば、生活は劇的に楽になります。
私自身のコードでこれを強制した方法は、最初の接続を閉じる前に 2 番目の接続を開こうとすると、Assert をスローする単一の静的 DataConnectionManager クラスを介してすべての接続を実行することです。そのクラスからのいくつかのスニペット:
private static int clientsOpen;
public static int ClientsOpen
{
get
{
return clientsOpen;
}
set
{
clientsOpen = value;
Debug.Assert(clientsOpen <= 1, "Bad things seem to happen when there's more than one open client.");
}
}
public static RoomServiceClient GetRoomServiceClient()
{
ClientsCreated++;
ClientsOpen++;
Logger.LogDebugMessage("Clients created: {0}; Clients open: {1}", ClientsCreated, ClientsOpen);
return new RoomServiceClient(GetDuplexHttpBinding(), GetDuplexHttpEndpoint());
}
public static void TryClientClose(RoomServiceClient client, bool waitForPendingCalls, Action<Exception> callback)
{
if (client != null && client.State != CommunicationState.Closed)
{
client.CloseCompleted += (sender, e) =>
{
ClientsClosed++;
ClientsOpen--;
Logger.LogDebugMessage("Clients closed: {0}; Clients open: {1}", ClientsClosed, ClientsOpen);
if (e.Error != null)
{
Logger.LogDebugMessage(e.Error.Message);
client.Abort();
}
closingIntentionally = false;
if (callback != null)
{
callback(e.Error);
}
};
closingIntentionally = true;
if (waitForPendingCalls)
{
WaitForPendingCalls(() => client.CloseAsync());
}
else
{
client.CloseAsync();
}
}
else
{
if (callback != null)
{
callback(null);
}
}
}
もちろん、厄介な部分は、接続が 1 つしかない場合、その接続が意図せずに閉じられたときにトラップして、再度開くようにする必要があることです。次に、さまざまなクラスが処理するために登録されたすべてのコールバックを再初期化する必要があります。それほど難しいことではありませんが、正しく行われていることを確認するのは面倒です。もちろん、その部分の自動テストは、不可能ではないにしても困難です。. .