Beispiel zum Streaming von FeedsStreaming Feeds Sample

In diesem Beispiel wird veranschaulicht, wie Syndication-Feeds verwaltet werden, die eine große Anzahl von Elementen enthalten.This sample demonstrates how to manage syndication feeds that contain large numbers of items. Auf dem Server zeigt das Beispiel, wie die Erstellung einzelner SyndicationItem-Objekte innerhalb des Feeds bis unmittelbar vor den Zeitpunkt verzögert werden kann, zu dem das Element in den Netzwerkstream geschrieben wird.On the server, the sample demonstrates how to delay the creation of individual SyndicationItem objects within the feed until immediately before the item is written to the network stream.

Auf dem Client zeigt das Beispiel, wie mit einem benutzerdefinierten Syndication-Feed-Formatierungsprogramm einzelne Elemente aus dem Netzwerkstream gelesen werden können, sodass der Feed, aus dem gelesen wird, nie vollständig im Speicher gepuffert wird.On the client, the sample shows how a custom syndication feed formatter can be used to read individual items from the network stream so that the feed being read is never fully buffered into memory.

Um die Streamingfähigkeiten der Syndication-API am besten demonstrieren zu können, verwendet dieses Beispiel ein etwas unwahrscheinliches Szenario, in dem der Server einen Feed zugänglich macht, der eine unbegrenzte Anzahl von Elementen enthält.To best demonstrate the streaming capability of the syndication API, this sample uses a somewhat unlikely scenario in which the server exposes a feed that contains an infinite number of items. In diesem Fall generiert der Server so lange neue Elemente und fügt sie in den Feed ein, bis er feststellt, dass der Client eine bestimmte Anzahl von Elementen (in der Standardeinstellung 10) aus dem Feed gelesen hat.In this case, the server continues generating new items into the feed until it determines that the client has read a specified number of items from the feed (by default, 10). Der Einfachheit halber werden sowohl der Client als auch der Server im gleichen Prozess implementiert und verfolgen mithilfe eines freigegebenen ItemCounter-Objekts, wie viele Elemente der Client produziert hat.For simplicity, both the client and the server are implemented in the same process and use a shared ItemCounter object to keep track of how many items the client has produced. Der ItemCounter-Typ ist nur zu dem Zweck vorhanden, damit das Beispielszenario sauber beendet werden kann. Für das Muster, das hier demonstriert wird, ist dieses Element nicht von Bedeutung.The ItemCounter type exists only for the purpose of allowing the sample scenario to terminate cleanly, and is not a core element of the pattern being demonstrated.

Die Demo nutzt Visual C#Visual C# Iteratoren (mit der yield``return Schlüsselwort Konstrukt).The demonstration makes use of Visual C#Visual C# iterators (using the yield``return keyword construct). Weitere Informationen finden Sie unterFor more information about zu Iteratoren finden Sie im Thema "Verwenden von Iteratoren" auf MSDN. iterators, see the "Using Iterators" topic on MSDN.

DienstService

Der Dienst implementiert einen grundlegenden WebGetAttribute-Vertrag, der aus einem Vorgang besteht, wie im folgenden Code gezeigt.The service implements a basic WebGetAttribute contract that consists of one operation, as shown in the following code.

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

Diesen Vertrag implementiert der Dienst mittels einer ItemGenerator-Klasse zum Erstellen eines potentiell unendlichen Streams von SyndicationItem-Instanzen mithilfe eines Iterators, wie im folgenden Code gezeigt.The service implements this contract by using an ItemGenerator class to create a potentially infinite stream of SyndicationItem instances using an iterator, as shown in the following code.

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

    }  
    ...  
}  

Beim Erstellen des Feeds verwendet die Dienstimplementierung statt einer gepufferten Auflistung von Elementen die Ausgabe von ItemGenerator.GenerateItems().When the service implementation creates the feed, the output of ItemGenerator.GenerateItems() is used instead of a buffered collection of items.

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

Infolgedessen wird der Elementstream nie vollständig im Arbeitsspeicher gepuffert.As a result, the item stream is never fully buffered into memory. Sie können dieses Verhalten beobachten, durch Festlegen eines Haltepunkts für die yield``return -Anweisung in der die ItemGenerator.GenerateItems() -Methode, und beachten Sie, dass dieser Haltepunkt erreicht wird, zum ersten Mal nach dem der Dienst das Ergebnis zurückgegeben hat die StreamedFeed() Methode.You can observe this behavior by setting a breakpoint on the yield``return statement inside of the ItemGenerator.GenerateItems() method and noting that this breakpoint is encountered for the first time after the service has returned the result of the StreamedFeed() method.

ClientClient

Der Client in diesem Beispiel verwendet eine benutzerdefinierte SyndicationFeedFormatter-Implementierung, die die Materialisierung einzelner Elemente im Feed verzögert, anstatt sie im Arbeitsspeicher zu puffern.The client in this sample uses a custom SyndicationFeedFormatter implementation that delays the materialization of individual items in the feed instead of buffering them into memory. Die benutzerdefinierte StreamedAtom10FeedFormatter-Instanz wird wie folgt verwendet:The custom StreamedAtom10FeedFormatter instance is used as follows.

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

SyndicationFeed feed = formatter.ReadFrom(reader);  

Normalerweise wird bei einem Aufruf von ReadFrom(XmlReader) die Steuerung erst dann zurückgegeben, wenn der gesamte Inhalt des Feeds aus dem Netzwerk gelesen und im Arbeitsspeicher gepuffert wurde.Normally, a call to ReadFrom(XmlReader) does not return until the entire contents of the feed have been read from the network and buffered into memory. Allerdings setzt das StreamedAtom10FeedFormatter-Objekt ReadItems(XmlReader, SyndicationFeed, Boolean) so außer Kraft, dass statt einer gepufferten Auflistung ein Iterator zurückgegeben wird, wie im folgenden Code gezeigt.However, the StreamedAtom10FeedFormatter object overrides ReadItems(XmlReader, SyndicationFeed, Boolean) to return an iterator instead of a buffered collection, as shown in the following code.

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

Demzufolge werden die einzelnen Elemente erst dann aus dem Netzwerk gelesen, wenn die Clientanwendung, die die Ergebnisse von ReadItems() durchläuft, bereit ist, sie zu verwenden.As a result, each item is not read from the network until the client application traversing the results of ReadItems() is ready to use it. Sie können dieses Verhalten beobachten, durch Festlegen eines Haltepunkts für die yield``return Anweisung innerhalb eines StreamedAtom10FeedFormatter.DelayReadItems() und bemerken, dass dieser Haltepunkt zum ersten Mal nach dem Aufruf von ReadFrom() abgeschlossen ist.You can observe this behavior by setting a breakpoint on the yield``return statement inside of StreamedAtom10FeedFormatter.DelayReadItems() and noticing that this breakpoint is encountered for the first time after the call to ReadFrom() completes.

Die folgenden Anweisungen zeigen, wie das Beispiel erstellt und ausgeführt wird.The following instructions show how to build and run the sample. Obwohl der Server keine Elemente mehr generiert, nachdem der Client 10 Elemente gelesen hat, zeigt die Ausgabe, dass der Client bedeutend mehr als 10 Elemente liest.Note that although the server stops generating items after the client has read 10 items, the output shows that the client reads significantly more than 10 items. Das liegt daran, dass die im Beispiel verwendete Netzwerkbindung Daten in Vier-Kilobyte-Segmenten übermittelt.This is because the networking binding used by the sample transmits data in four-kilobyte (KB) segments. Daher empfängt der Client 4 KB Elementdaten, bevor er die Gelegenheit hat, auch nur ein einziges Element zu lesen.As such, the client receives 4KB of item data before it has the opportunity to read even one item. Dieses Verhalten ist normal (wenn gestreamte HTTP-Daten in Segmenten einer vernünftigen Größe gesendet werden, ist das Leistungsverhalten besser).This is normal behavior (sending streamed HTTP data in reasonably-sized segments increases performance).

So können Sie das Beispiel einrichten, erstellen und ausführenTo set up, build, and run the sample

  1. Stellen Sie sicher, dass Sie ausgeführt haben die Setupprozedur für die Windows Communication Foundation-Beispiele zum einmaligen.Ensure that you have performed the One-Time Setup Procedure for the Windows Communication Foundation Samples.

  2. Um die C#- oder Visual Basic .NET-Edition der Projektmappe zu erstellen, befolgen Sie die unter Building the Windows Communication Foundation Samplesaufgeführten Anweisungen.To build the C# or Visual Basic .NET edition of the solution, follow the instructions in Building the Windows Communication Foundation Samples.

  3. Um das Beispiel in einer einzelnen oder computerübergreifenden Konfiguration ausführen möchten, folgen Sie den Anweisungen Ausführen der Windows Communication Foundation-Beispiele.To run the sample in a single- or cross-machine configuration, follow the instructions in Running the Windows Communication Foundation Samples.

Wichtig

Die Beispiele sind möglicherweise bereits auf dem Computer installiert.The samples may already be installed on your computer. Suchen Sie nach dem folgenden Verzeichnis (Standardverzeichnis), bevor Sie fortfahren.Check for the following (default) directory before continuing.

<InstallDrive>:\WF_WCF_Samples

Wenn dieses Verzeichnis nicht vorhanden ist, rufen Sie Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) Samples for .NET Framework 4 auf, um alle Windows Communication Foundation (WCF)Windows Communication Foundation (WCF) - und WFWF -Beispiele herunterzuladen.If this directory does not exist, go to Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) Samples for .NET Framework 4 to download all Windows Communication Foundation (WCF)Windows Communication Foundation (WCF) and WFWF samples. Dieses Beispiel befindet sich im folgenden Verzeichnis.This sample is located in the following directory.

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

Siehe auchSee Also

Eigenständiger DiagnosefeedStand-Alone Diagnostics Feed