Esempio trasmissione feed

Nell’esempio StreamingFeeds, viene illustrato come gestire feed che contengono numerosi elementi. Nel server, l'esempio illustra come rimandare la creazione di oggetti SyndicationItem singoli all'interno del feed fino a immediatamente prima della scrittura dell'elemento nel flusso della rete.

Sul client, l'esempio illustra come un formattatore del feed di distribuzione personalizzato possa essere utilizzato per leggere elementi singoli dal flusso della rete così che il feed letto non sia mai pienamente memorizzato nel buffer.

Per dimostrare al meglio la funzionalità del flusso di diffusione API, questo esempio utilizza uno scenario piuttosto improbabile nel quale il server espone un feed che contiene un numero infinito di elementi. In questo caso, il server continua a generare nuovi elementi nel feed fino a determinare che il client ha letto un numero specificato di elementi dal feed (10, per impostazione predefinita). Per semplicità, sia il client che il server vengono implementati nello stesso processo e utilizzano un oggetto ItemCounter condiviso per tenere traccia del numero di elementi prodotti dal client. Il tipo ItemCounter esiste solo allo scopo di consentire allo scenario di esempio di terminare in modo pulito e non è un elemento principale dello schema illustrato.

La dimostrazione si avvale di iteratori di Visual C# (che utilizzano il costrutto di parole chiave yield return). Per altre informazioni sugli iteratori, vedere l'argomento "Uso di iteratori" su MSDN.

Servizio

Il servizio implementa un contratto WebGetAttribute di base che è costituito da un'operazione, come mostra il codice seguente.

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

Il servizio implementa il contratto utilizzando una classe ItemGenerator per creare un flusso potenzialmente infinito di istanze SyndicationItem utilizzando un iteratore, come mostra il codice seguente.

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

    }
    ...
}

Quando l'implementazione del servizio crea il feed, viene utilizzato l'output di ItemGenerator.GenerateItems() invece di una raccolta di elementi memorizzato nel 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();
}

Di conseguenza, il flusso dell'elemento non viene mai memorizzato pienamente nel buffer. È possibile osservare questo comportamento impostando un punto di interruzione sull'istruzione yield return nel metodo ItemGenerator.GenerateItems() e notando che il punto di interruzione si incontra per la prima volta dopo che il servizio ha restituito il risultato del metodo StreamedFeed().

Client

Il client in questo esempio utilizza un'implementazione personalizzata della classe SyndicationFeedFormatter che rimanda la materializzazione di elementi singoli nel feed invece di memorizzarli nel buffer. Di seguito viene illustrata l'istanza personalizzata di StreamedAtom10FeedFormatter:

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

SyndicationFeed feed = formatter.ReadFrom(reader);

Normalmente, una chiamata al metodo ReadFrom(XmlReader) non restituisce alcun risultato fino a che il contenuto intero del feed non sia stato letto dalla rete e memorizzato nel buffer. Tuttavia, l'oggetto StreamedAtom10FeedFormatter ignora il metodo ReadItems(XmlReader, SyndicationFeed, Boolean) per restituire un iteratore invece di una raccolta memorizzata nel buffer, come mostra il codice seguente.

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

Di conseguenza, ogni elemento non viene letto dalla rete fino a che l'applicazione client che attraversa i risultati di ReadItems() non è pronta a utilizzarli. È possibile osservare questo comportamento impostando un punto di interruzione sull'istruzione yield return nel metodo StreamedAtom10FeedFormatter.DelayReadItems() e notando che il punto di interruzione si incontra per la prima volta dopo il completamento della chiamata a ReadFrom().

Nelle istruzioni seguenti viene illustrato come compilare ed eseguire l'esempio. Notare che anche se il server smette di generare elementi dopo che il client ha letto 10 elementi, l'output mostra che il client ne legge molti più di 10. Ciò avviene perché l'associazione di rete utilizzata dall'esempio trasmette dati in segmenti di quattro kilobyte (KB). Di conseguenza, il client riceve 4 KB di dati dell'elemento prima che abbia la possibilità di leggere il primo elemento. Si tratta di un comportamento normale (trasmettere dati HTTP in segmenti di dimensioni ragionevolmente grandi aumenta le prestazioni).

Per impostare, compilare ed eseguire l'esempio

  1. Assicurarsi di aver eseguito la Procedura di installazione singola per gli esempi di Windows Communication Foundation.

  2. Per compilare l'edizione in C# o Visual Basic .NET della soluzione, seguire le istruzioni in Building the Windows Communication Foundation Samples.

  3. Per eseguire l'esempio in un solo computer o tra computer diversi, seguire le istruzioni in Esecuzione degli esempi di Windows Communication Foundation.

Vedi anche