Partager via


Exemple de flux de diffusion en continu

L’exemple StreamingFeeds montre comment gérer les flux de syndication qui contiennent un grand nombre d’éléments. Sur le serveur, l’exemple montre comment retarder la création d’objets individuels SyndicationItem dans le flux jusqu’à ce que l’élément soit écrit dans le flux réseau.

Sur le client, l’exemple montre comment un formateur de flux de syndication personnalisé peut être utilisé pour lire des éléments individuels à partir du flux réseau afin que le flux lu ne soit jamais entièrement mis en mémoire tampon.

Pour mieux illustrer la fonctionnalité de diffusion en continu de l’API de syndication, cet exemple utilise un scénario quelque peu improbable dans lequel le serveur expose un flux qui contient un nombre infini d’éléments. Dans ce cas, le serveur continue de générer de nouveaux éléments dans le flux jusqu’à ce qu’il détermine que le client a lu un nombre spécifié d’éléments à partir du flux (par défaut, 10). Par souci de simplicité, le client et le serveur sont implémentés dans le même processus et utilisent un objet partagé ItemCounter pour suivre le nombre d’éléments produits par le client. Le ItemCounter type existe uniquement pour permettre à l’exemple de scénario de se terminer correctement et n’est pas un élément principal du modèle présenté.

La démonstration utilise des itérateurs Visual C# (à l’aide de la construction de yield return mot clé). Pour plus d’informations sur les itérateurs, consultez la rubrique « Utilisation d’itérateurs » sur MSDN.

Service

Le service implémente un contrat de base WebGetAttribute qui se compose d’une opération, comme indiqué dans le code suivant.

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

Le service implémente ce contrat à l’aide d’une ItemGenerator classe pour créer un flux potentiellement infini d’instances SyndicationItem à l’aide d’un itérateur, comme indiqué dans le code suivant.

class ItemGenerator
{
    public IEnumerable<SyndicationItem> GenerateItems()
    {
        while (counter.GetCount() < maxItemsRead)
        {
            itemsReturned++;
            yield return CreateNextItem();
        }

    }
    ...
}

Lorsque l’implémentation du service crée le flux, la sortie est ItemGenerator.GenerateItems() utilisée au lieu d’une collection d’éléments mis en mémoire tampon.

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();
}

Par conséquent, le flux d’élément n’est jamais entièrement mis en mémoire tampon. Vous pouvez observer ce comportement en définissant un point d’arrêt sur l’instruction à l’intérieur yield return de la ItemGenerator.GenerateItems() méthode et en notant que ce point d’arrêt est rencontré pour la première fois après que le service a retourné le résultat de la StreamedFeed() méthode.

Client

Le client de cet exemple utilise une implémentation personnalisée SyndicationFeedFormatter qui retarde la matérialisation d’éléments individuels dans le flux au lieu de les mettre en mémoire tampon. L’instance personnalisée StreamedAtom10FeedFormatter est utilisée comme suit.

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

SyndicationFeed feed = formatter.ReadFrom(reader);

Normalement, un appel à ReadFrom(XmlReader) ne retourne pas tant que le contenu entier du flux n’a pas été lu à partir du réseau et mis en mémoire tampon. Toutefois, l’objet StreamedAtom10FeedFormatter remplace ReadItems(XmlReader, SyndicationFeed, Boolean) le retour d’un itérateur au lieu d’une collection mise en mémoire tampon, comme indiqué dans le code suivant.

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();
}

Par conséquent, chaque élément n’est pas lu à partir du réseau tant que l’application cliente n’a pas parcouru les résultats d’une ReadItems() application cliente prête à l’utiliser. Vous pouvez observer ce comportement en définissant un point d’arrêt sur l’instruction à l’intérieur yield return et StreamedAtom10FeedFormatter.DelayReadItems() en notant que ce point d’arrêt est rencontré pour la première fois après l’exécution de l’appel ReadFrom() .

Les instructions suivantes montrent comment générer et exécuter l’exemple. Notez que bien que le serveur cesse de générer des éléments une fois que le client a lu 10 éléments, la sortie indique que le client lit beaucoup plus de 10 éléments. Cela est dû au fait que la liaison réseau utilisée par l’exemple transmet des données en segments de quatre kilooctets (Ko). Par conséquent, le client reçoit 4 Ko de données d’élément avant qu’il ait la possibilité de lire un seul élément. Il s’agit d’un comportement normal (l’envoi de données HTTP diffusées en continu dans des segments de taille raisonnable augmente les performances).

Pour configurer, générer et exécuter l’exemple

  1. Assurez-vous d’avoir effectué la Procédure d’installation unique pour les exemples Windows Communication Foundation.

  2. Pour générer l’édition C# ou Visual Basic .NET de la solution, conformez-vous aux instructions figurant dans Building the Windows Communication Foundation Samples.

  3. Pour exécuter l’exemple dans une configuration à un ou plusieurs ordinateurs, conformez-vous aux instructions figurant dans la rubrique Exécution des exemples Windows Communication Foundation.

Voir aussi