Я работаю над приложением n-Tier, использующим WCF между слоями, так что:
Уровень 1: приложение Silverlight
Вызывает поисковый запрос
IClientBroker clientBroker = UIContext.CreateWcfInterface<IClientBroker>("Data/ClientBroker.svc");
clientBroker.BeginSearchForClients(SearchTerm, 20, (result) =>
{
SearchResult[] results = ((IClientBroker)result.AsyncState).EndSearchForClients(result).ToArray();
// do stuff, update UI, etc.
}, clientBroker);
Уровень 2: веб-служба WCF, использующая basicHttp для вызова Silverlight. Это действует как прокси для 3-го уровня.
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
class ClientBroker : IClientBroker
{
[OperationContract] // as defined in IClientBroker
public SearchResult[] SearchForClients(string keywords, int? maxResults)
{
ClientBrokerClient clientBroker = CreateClientBrokerClient();
SearchResult[] searchResults=clientBroker.SearchForClients(keywords, maxResults);
return searchResults;
}
}
Уровень 3: это «сервер», так как он предлагает конечную точку net.tcp (позволяющую защищенным клиентам подключаться без использования Silverlight). Это конечная цель запроса.
public class ClientBroker : IClientBroker // note this is different to tier 2 interface
{
public SearchResult[] SearchForClients(string keywords, int? maxResults)
{
// do stuff
if (maxResults.HasValue)
{
return results.Take(maxResults.Value).ToArray();
}
else
{
return results.ToArray();
}
}
}
Итак, мои звонки идут:
Silverlight -> httpBasic -> IIS-служба прокси WCF -> net.tcp -> EXE-служба WCF
Это хорошо работает. Я могу передавать заголовки через слои, поддерживать сессии и т. Д. И это довольно аккуратно.
НО это всего лишь несколько звонков, чтобы вызвать тайм-аут в сообщении.
Время, необходимое серверу-EXE для выполнения своей работы, ничтожно мало.
Проблема, с которой я сталкиваюсь, заключается в том, что сервер «зависает» при возврате результатов на уровень 2.
Я думаю, это связано с блокировкой потока.
Я оглянулся и увидел, что идеальный способ сделать это - заставить мой Tier 2 работать асинхронно, как показано в коде ниже:
public SearchResult[] SearchForClients(string keywords, int? maxResults)
{
ClientBrokerClient clientBroker = CreateClientBrokerClient();
clientBroker.BeginSearchForClients(keywords, maxResults, result =>
{
SearchResult[] searchResults=((ClientBrokerClient)result.AsyncState).EndSearchForClients(result);
// how to return results from here?
}, clientBroker);
}
Но как мне этого добиться, когда мой клиент уровня 1 ожидает результата этого метода, который просто выпадет прямо перед выполнением обратного вызова? Я что-то упустил в моей конструкции моих методов OperationContract?
UPDATE:
С тех пор мой сервер (уровень 3) прошел путь от клиента, избегая уровня 2, делая много запросов от него. Кажется, что канал WCF net.tcp для Уровня 3 очень прочный.
ОБНОВЛЕНИЕ 2:
Этот пост в блоге описан с использованием шаблона IAsyncResult, к которому я здесь обратился. Я лаю не на том дереве? http://blogs.msdn.com/wenlong/archive/2009/02/09/scale-wcf-application-better-with-asynchronous-programming.aspx
ОБНОВЛЕНИЕ 3:
Хорошо, этот абзац из этого блога:
"Если вы строите N-ярусный WCF
услуги, у вас будет сервис WCF
операции вызова клиентских прокси WCF
для других бэкэнд-сервисов. В этом
случае, вы должны убедиться, что
средний уровень (уровень маршрутизации) имеет
асинхронная операция обслуживания
вызов асинхронного прокси WCF
операции. Таким образом, ваш
средний уровень не закончится
при обработке многих медленных операций. "
, кажется, подтверждает мои подозрения, что проблема заключается в среднем уровне (Уровень 2). Как я могу добиться этой асинхронности Begin / End? Нужно ли делать это вручную или я могу сохранить инструменты VS для генерации прокси-классов для меня? (ДЕЙСТВИТЕЛЬНО не хочу делать это вручную, контракты имеют некоторую степень изменчивости)