Oharra
Orrialde honetara sartzeak baimena behar du. Saioa hasteko edo direktorioak aldatzen saia zaitezke.
Orrialde honetara sartzeak baimena behar du. Direktorioak aldatzen saia zaitezke.
En el ejemplo StreamingFeeds se muestra cómo administrar fuentes de distribución que contienen un gran número de elementos. En el servidor, el ejemplo muestra cómo retrasar la creación de objetos SyndicationItem individuales dentro de la fuente hasta justo antes de que el elemento se escriba en el flujo de red.
En el cliente, el ejemplo muestra cómo se puede utilizar el formateador de fuente de distribución personalizado para leer los elementos individuales de la secuencia de red para que la fuente que se está leyendo nunca se almacene completamente en el búfer en la memoria.
Para demostrar mejor la funcionalidad de streaming de la API de distribución, en este ejemplo se usa un escenario poco probable en el que el servidor expone una fuente que contiene un número infinito de elementos. En este caso, el servidor continúa generando nuevos elementos en la fuente hasta que determina que el cliente ha leído un número especificado de elementos de la fuente (de forma predeterminada, 10). Por motivos de simplicidad, tanto el cliente como el servidor se implementan en el mismo proceso y usan un objeto compartido ItemCounter para realizar un seguimiento de cuántos elementos ha generado el cliente. El ItemCounter tipo solo existe para permitir que el escenario de ejemplo finalice limpiamente y no es un elemento principal del patrón que se muestra.
La demostración usa iteradores de Visual C# (mediante la estructura de la palabra clave yield return). Para obtener más información sobre los iteradores, vea el tema "Using Iterators" (Uso de iteradores) en MSDN.
Servicio
El servicio implementa un contrato básico WebGetAttribute que consta de una operación, como se muestra en el código siguiente.
[ServiceContract]
interface IStreamingFeedService
{
[WebGet]
[OperationContract]
Atom10FeedFormatter StreamedFeed();
}
El servicio implementa este contrato mediante una ItemGenerator clase para crear una secuencia potencialmente infinita de SyndicationItem instancias mediante un iterador, como se muestra en el código siguiente.
class ItemGenerator
{
public IEnumerable<SyndicationItem> GenerateItems()
{
while (counter.GetCount() < maxItemsRead)
{
itemsReturned++;
yield return CreateNextItem();
}
}
...
}
Cuando la implementación del servicio crea la fuente, se usa el resultado de ItemGenerator.GenerateItems() en lugar de una colección almacenada en búfer de elementos.
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, la secuencia del elemento nunca se almacena totalmente en búfer en la memoria. Puede observar este comportamiento estableciendo un punto de interrupción en la yield return instrucción dentro del ItemGenerator.GenerateItems() método y teniendo en cuenta que este punto de interrupción se encuentra por primera vez después de que el servicio haya devuelto el resultado del StreamedFeed() método.
Cliente
El cliente en este ejemplo utiliza una implementación SyndicationFeedFormatter personalizada que retrasa la materialización de elementos individuales en la fuente en lugar de almacenarlos en búfer en la memoria. La instancia personalizada StreamedAtom10FeedFormatter se usa de la manera siguiente.
XmlReader reader = XmlReader.Create("http://localhost:8000/Service/Feeds/StreamedFeed");
StreamedAtom10FeedFormatter formatter = new StreamedAtom10FeedFormatter(counter);
SyndicationFeed feed = formatter.ReadFrom(reader);
Normalmente, una llamada a ReadFrom(XmlReader) no retorna hasta que se haya leído todo el contenido del feed desde la red y se haya almacenado en un búfer en la memoria. Sin embargo, el objeto StreamedAtom10FeedFormatter invalida ReadItems(XmlReader, SyndicationFeed, Boolean) para devolver un iterador en lugar de una colección almacenada en búfer, tal y como se muestra en el código siguiente.
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 elemento no se lee de la red hasta que la aplicación cliente que recorre los resultados de ReadItems() está lista para usarlos. Puede observar este comportamiento estableciendo un punto de interrupción en la yield return instrucción dentro de StreamedAtom10FeedFormatter.DelayReadItems() y notando que este punto de interrupción se encuentra por primera vez después de que se complete la llamada a ReadFrom() .
En las instrucciones siguientes se muestra cómo compilar y ejecutar el ejemplo. Tenga en cuenta que aunque el servidor deja de generar elementos después de que el cliente haya leído 10 elementos, la salida muestra que el cliente lee significativamente más de 10 elementos. Esto se debe a que el enlace de red usado por el ejemplo transmite datos en segmentos de cuatro kilobytes (KB). Por lo tanto, el cliente recibe 4 KB de datos de elementos antes de tener la oportunidad de leer incluso un elemento. Este es un comportamiento normal (el envío de datos HTTP transmitidos en segmentos de tamaño razonable aumenta el rendimiento).
Para configurar, compilar y ejecutar el ejemplo
Asegúrese de que ha realizado el procedimiento de instalación única para los ejemplos de Windows Communication Foundation.
Para compilar el código C# o Visual Basic .NET Edition de la solución, siga las instrucciones de Building the Windows Communication Foundation Samples.
Para ejecutar el ejemplo en una configuración de una máquina única o entre máquinas, siga las instrucciones de Ejecución de los ejemplos de Windows Communication Foundation.