Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
O exemplo do StreamingFeeds demonstra como gerenciar feeds de sindicalização que contêm um grande número de itens. No servidor, o exemplo demonstra como atrasar a criação de objetos individuais SyndicationItem no feed até imediatamente antes que o item seja gravado no fluxo de rede.
No cliente, o exemplo mostra como um formatador de feed de sindicalização personalizado pode ser usado para ler itens individuais do fluxo de rede para que o feed que está sendo lido nunca seja totalmente armazenado em buffer na memória.
Para demonstrar melhor a capacidade de streaming da API de syndicação, este exemplo usa um cenário um tanto improvável no qual o servidor expõe um feed que contém uma quantidade infinita de itens. Nesse caso, o servidor continua gerando novos itens no feed até determinar que o cliente leu um número especificado de itens do feed (por padrão, 10). Para simplificar, o cliente e o servidor são implementados no mesmo processo e usam um objeto compartilhado ItemCounter para acompanhar quantos itens o cliente produziu. O ItemCounter tipo existe apenas para permitir que o cenário de exemplo seja encerrado de forma limpa e não é um elemento central do padrão que está sendo demonstrado.
A demonstração usa iteradores do Visual C# (usando o constructo da yield return palavra-chave). Para obter mais informações sobre iteradores, consulte o tópico "Usando Iteradores" no MSDN.
Serviço
O serviço implementa um contrato básico WebGetAttribute que consiste em uma operação, conforme mostrado no código a seguir.
[ServiceContract]
interface IStreamingFeedService
{
[WebGet]
[OperationContract]
Atom10FeedFormatter StreamedFeed();
}
O serviço implementa esse contrato usando uma ItemGenerator classe para criar um fluxo potencialmente infinito de SyndicationItem instâncias usando um iterador, conforme mostrado no código a seguir.
class ItemGenerator
{
public IEnumerable<SyndicationItem> GenerateItems()
{
while (counter.GetCount() < maxItemsRead)
{
itemsReturned++;
yield return CreateNextItem();
}
}
...
}
Quando a implementação do serviço cria o feed, a saída de ItemGenerator.GenerateItems() é usada em vez de uma coleção de itens em buffer.
public Atom10FeedFormatter StreamedFeed()
{
SyndicationFeed feed = new SyndicationFeed("Streamed feed", "Feed to test streaming", null);
//Generate an infinite stream of items. Both the client and the service share
//a reference to the ItemCounter, which allows the sample to terminate
//execution after the client has read 10 items from the stream
ItemGenerator itemGenerator = new ItemGenerator(this.counter, 10);
feed.Items = itemGenerator.GenerateItems();
return feed.GetAtom10Formatter();
}
Como resultado, o fluxo de itens nunca é totalmente armazenado em buffer na memória. Você pode observar esse comportamento definindo um ponto de interrupção na yield return instrução dentro do ItemGenerator.GenerateItems() método e observando que esse ponto de interrupção é encontrado pela primeira vez depois que o serviço retorna o resultado do StreamedFeed() método.
Cliente
O cliente neste exemplo usa uma implementação personalizada SyndicationFeedFormatter que atrasa a materialização de itens individuais no feed em vez de armazená-los em buffer na memória. A instância personalizada StreamedAtom10FeedFormatter é usada da seguinte maneira.
XmlReader reader = XmlReader.Create("http://localhost:8000/Service/Feeds/StreamedFeed");
StreamedAtom10FeedFormatter formatter = new StreamedAtom10FeedFormatter(counter);
SyndicationFeed feed = formatter.ReadFrom(reader);
Normalmente, uma chamada para ReadFrom(XmlReader) não retorna até que todo o conteúdo do feed tenha sido lido da rede e armazenado na memória. No entanto, o StreamedAtom10FeedFormatter objeto substitui ReadItems(XmlReader, SyndicationFeed, Boolean) para retornar um iterador em vez de uma coleção em buffer, conforme mostrado no código a seguir.
protected override IEnumerable<SyndicationItem> ReadItems(XmlReader reader, SyndicationFeed feed, out bool areAllItemsRead)
{
areAllItemsRead = false;
return DelayReadItems(reader, feed);
}
private IEnumerable<SyndicationItem> DelayReadItems(XmlReader reader, SyndicationFeed feed)
{
while (reader.IsStartElement("entry", "http://www.w3.org/2005/Atom"))
{
yield return this.ReadItem(reader, feed);
}
reader.ReadEndElement();
}
Como resultado, cada item não é lido da rede até que o aplicativo cliente que percorre os resultados ReadItems() esteja pronto para usá-lo. Você pode observar esse comportamento definindo um ponto de interrupção na instrução yield return dentro de StreamedAtom10FeedFormatter.DelayReadItems() e percebendo que esse ponto de interrupção é encontrado pela primeira vez após a conclusão da chamada ReadFrom().
As instruções a seguir mostram como compilar e executar o exemplo. Observe que, embora o servidor pare de gerar itens depois que o cliente ler 10 itens, a saída mostra que o cliente lê significativamente mais de 10 itens. Isso ocorre porque a associação de rede usada pelo exemplo transmite dados em segmentos KB (quatro quilobytes). Assim, o cliente recebe 4KB de dados de item antes de ter a oportunidade de ler até mesmo um item. Esse é um comportamento normal (o envio de dados HTTP transmitidos em segmentos de tamanho razoável aumenta o desempenho).
Para configurar, compilar e executar o exemplo
Verifique se você executou o Procedimento de instalação avulsa dos exemplos do Windows Communication Foundation.
Para compilar a edição .NET do C# ou do Visual Basic da solução, siga as instruções contidas em Como Compilar as Amostras do Windows Communication Foundation.
Para executar o exemplo em uma configuração única ou entre máquinas, siga as instruções em Executando os exemplos do Windows Communication Foundation.