Я использую Silverlight с WCF с V2 (теперь работает с V4), и вот что я нашел. В целом, он работает очень хорошо, чтобы открыть одного клиента и просто использовать одного клиента для всех коммуникаций. И если вы не используете DuplexHttBinding, он также отлично работает, чтобы делать как раз наоборот, каждый раз открывать новое соединение, а затем закрывать его, когда вы закончите. И из-за того, как Microsoft сконструировала клиент WCF в Silverlight, вы не увидите большой разницы в производительности между тем, чтобы один клиент открывался все время против создания нового клиента с каждым запросом. (Но если вы создаете нового клиента с каждым запросом, сделайте чертовски уверенным, что вы его также закрываете.)
Теперь, если вы используете DuplexHttBinding, то есть, если вы хотите вызвать методы на клиент с сервера, конечно, важно, чтобы вы не закрывали клиента с каждым запросом. Это просто здравый смысл. Однако о том, что ни одна из документации не говорит вам, но которую я считаю абсолютно критичной, заключается в том, что если вы используете DuplexHttBinding, вы должны иметь только один экземпляр клиента, который открывается сразу. В противном случае вы столкнетесь со всеми неприятными проблемами с таймаутом, которые действительно будут действительно сложными для устранения неполадок. Ваша жизнь будет значительно проще, если у вас будет только одно соединение.
Способ, которым я выполнял это в своем собственном коде, заключается в том, чтобы запускать все мои подключения через один статический класс DataConnectionManager, который выдает Assert, если я попытаюсь открыть второе соединение перед закрытием первого. Несколько отрывков из этого класса:
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);
}
}
}
Раздражает часть, конечно, если у вас есть только одно соединение, вы должны ловушку, когда это соединение закрывается непреднамеренно и попытаться открыть его. И тогда вам нужно повторно инициализировать все обратные вызовы, которые были зарегистрированы вашими различными классами. На самом деле это не так сложно, но это раздражает, чтобы убедиться, что все сделано правильно. И, конечно, автоматическое тестирование этой части сложно, если не невозможно. , ,
Ответ, вероятно, зависит от вашего сервиса. Создание прокси-сервера дорого, но отслеживать этот единственный прокси и управлять любыми ошибками может быть сложно. – Bryant