Ejemplo de suministros de transmisión por secuencias

Este ejemplo muestra cómo administrar las fuentes de sindicación que contienen grandes cantidades 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 del flujo de red para que la fuente que se está leyendo nunca se almacene completamente en el búfer en la memoria.

Para mostrar mejor la capacidad de transmisión por secuencias de la API de sindicación, este ejemplo utiliza un escenario algo improbable en el que el servidor expone una fuente que contiene un número infinito de elementos. En este caso, el servidor sigue generando los nuevos elementos en la fuente hasta que determine que el cliente ha leído un número especificado de elementos de la fuente (de forma predeterminada, 10). Para simplificar, el cliente y el servidor se implementan en el mismo proceso y utilizan un objeto ItemCounter compartido para realizar un seguimiento del número de elementos que el cliente ha generado. El tipo ItemCounter solo existe con el propósito de permitir la finalización del escenario de ejemplo y no es un elemento básico del modelo que se está mostrando.

La demostración utiliza iteradores Visual C# (mediante la construcción de palabra clave yieldreturn). Para obtener más información sobre los iteradores, consulte el tema sobre el uso de iteradores en MSDN.

Servicio

El servicio implementa un contrato WebGetAttribute básico que está compuesto de una operación, tal y como se muestra en el código siguiente.

[ServiceContract]
interface IStreamingFeedService
{
    [WebGet]
    [OperationContract]
    Atom10FeedFormatter StreamedFeed();
}

El servicio implementa este contrato utilizando una clase ItemGenerator para crear una secuencia potencialmente infinita de instancias SyndicationItem mediante un iterador, tal y 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 instrucción yieldreturn dentro del método ItemGenerator.GenerateItems() 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 método StreamedFeed().

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 StreamedAtom10FeedFormatter personalizada se usa de la manera siguiente.

XmlReader reader = XmlReader.Create("https://localhost:8000/Service/Feeds/StreamedFeed");
StreamedAtom10FeedFormatter formatter = new StreamedAtom10FeedFormatter(counter);

SyndicationFeed feed = formatter.ReadFrom(reader);

Normalmente, una llamada a ReadFrom no se devuelve hasta que el contenido completo de la fuente se haya leído desde la red y almacenado en búfer en la memoria. Sin embargo, el objeto StreamedAtom10FeedFormatter invalida ReadItems 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, no se lee cada elemento desde la red hasta que la aplicación cliente que atraviesa los resultados de ReadItems() esté lista para utilizarlo. Puede observar este comportamiento estableciendo un punto de interrupción en la instrucción yieldreturn dentro de StreamedAtom10FeedFormatter.DelayReadItems() y teniendo en cuenta que este punto de interrupción aparece por primera vez después de que la llamada a ReadFrom() se complete.

Las instrucciones siguientes muestran cómo compilar y ejecutar el ejemplo. Tenga en cuenta que aunque el servidor deja de generar los elementos después de que el cliente haya leído diez elementos, la salida muestra que el cliente lee significativamente más de diez elementos. Esto es porque el enlace de conexión en red utilizado por el ejemplo transmite los datos en segmentos de cuatro kilobytes (KB). Como tal, el cliente recibe 4 KB de datos de elemento antes de tener la oportunidad incluso de leer un elemento. Se trata del comportamiento normal (el envío de datos de secuencia de HTTP en segmentos de tamaño razonable aumenta el rendimiento).

Para configurar, compilar y ejecutar el ejemplo

  1. Asegúrese de realizar los Procedimiento de instalación única para los ejemplos de Windows Communication Foundation.

  2. Para compilar el código C# o Visual Basic .NET Edition de la solución, siga las instrucciones de Compilación de los ejemplos de Windows Communication Foundation.

  3. Para ejecutar el ejemplo en una configuración con un único equipo o con varios, siga las instrucciones de Running the Windows Communication Foundation Samples.

Bb472423.Important(es-es,VS.100).gif Nota:
Puede que los ejemplos ya estén instalados en su equipo. Compruebe el siguiente directorio (valor predeterminado) antes de continuar.

<InstallDrive>:\WF_WCF_Samples

Si no existe este directorio, vaya a la página de ejemplos de Windows Communication Foundation (WCF) y Windows Workflow Foundation (WF) Samples para .NET Framework 4 para descargar todos los ejemplos de WF y Windows Communication Foundation (WCF). Este ejemplo se encuentra en el siguiente directorio.

<InstallDrive>:\WF_WCF_Samples\WCF\Extensibility\Syndication\StreamingFeeds

Vea también

Tareas

Ejemplo de fuente de diagnósticos independientes