Sdílet prostřednictvím


Ukázka informačních kanálů streamování

Ukázka StreamingFeeds ukazuje, jak spravovat syndikační kanály, které obsahují velký počet položek. Ukázka na serveru ukazuje, jak zpozdit vytváření jednotlivých SyndicationItem objektů v informačním kanálu až těsně před zápisem položky do síťového datového proudu.

V klientovi ukázka ukazuje, jak se dá vlastní formátovací modul syndikačního kanálu použít ke čtení jednotlivých položek ze síťového datového proudu, aby nebyl nikdy plně uložen do vyrovnávací paměti.

Aby bylo možné nejlépe předvést schopnost streamování rozhraní API syndikace, používá tato ukázka poněkud nepravděpodobné scénáře, ve kterém server zveřejňuje informační kanál, který obsahuje neomezený počet položek. V tomto případě server pokračuje v generování nových položek do informačního kanálu, dokud nezomezí, že klient přečte zadaný počet položek z informačního kanálu (ve výchozím nastavení 10). Pro zjednodušení se klient i server implementují ve stejném procesu a používají sdílený ItemCounter objekt ke sledování počtu položek, které klient vytvořil. Typ ItemCounter existuje pouze pro účely povolení čistého ukončení ukázkového scénáře a není základním prvkem modelu, který je demonstrován.

Ukázka využívá iterátory jazyka Visual C# (pomocí konstruktoru klíčového yield return slova). Další informace o iterátorech najdete v tématu Používání iterátorů na webu MSDN.

Služba

Služba implementuje základní WebGetAttribute kontrakt, který se skládá z jedné operace, jak je znázorněno v následujícím kódu.

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

Služba implementuje tento kontrakt pomocí ItemGenerator třídy k vytvoření potenciálně nekonečného streamu SyndicationItem instancí pomocí iterátoru, jak je znázorněno v následujícím kódu.

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

    }
    ...
}

Když implementace služby vytvoří informační kanál, použije se výstup ItemGenerator.GenerateItems() namísto kolekce položek ve vyrovnávací paměti.

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

Výsledkem je, že stream položky není nikdy plně uložen do vyrovnávací paměti. Toto chování můžete sledovat tak, že nastavíte zarážku na yield return příkaz uvnitř ItemGenerator.GenerateItems() metody a všimněte si, že tato zarážka je zjištěna poprvé po vrácení výsledku StreamedFeed() metody služba.

Klient

Klient v této ukázce používá vlastní SyndicationFeedFormatter implementaci, která zpožďuje materializaci jednotlivých položek v informačním kanálu místo ukládání do vyrovnávací paměti. Vlastní StreamedAtom10FeedFormatter instance se používá následujícím způsobem.

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

SyndicationFeed feed = formatter.ReadFrom(reader);

Za normálních okolností se volání ReadFrom(XmlReader) nevrací, dokud se celý obsah informačního kanálu nečte ze sítě a do vyrovnávací paměti. Objekt StreamedAtom10FeedFormatter však přepíše ReadItems(XmlReader, SyndicationFeed, Boolean) , aby vrátil iterátor místo kolekce s vyrovnávací pamětí, jak je znázorněno v následujícím kódu.

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

V důsledku toho se každá položka nepřečte ze sítě, dokud klientská aplikace neprochází výsledky ReadItems() , které jsou připravené k jeho použití. Toto chování můžete sledovat tak, že nastavíte zarážku na yield return příkaz uvnitř StreamedAtom10FeedFormatter.DelayReadItems() příkazu a zjistíte, že se tato zarážka poprvé po dokončení volání ReadFrom() zjistí.

Následující pokyny ukazují, jak sestavit a spustit ukázku. Všimněte si, že i když server přestane generovat položky po přečtení 10 položek klienta, výstup ukazuje, že klient čte výrazně více než 10 položek. Důvodem je to, že síťová vazba používaná ukázkou přenáší data ve čtyřkilobajtových segmentech (KB). Klient proto obdrží 4 kB dat položek, než bude mít možnost číst i jednu položku. Toto je normální chování (odesílání streamovaných dat HTTP v segmentech s rozumnou velikostí zvyšuje výkon).

Nastavení, sestavení a spuštění ukázky

  1. Ujistěte se, že jste pro ukázky windows Communication Foundation provedli jednorázovou instalační proceduru.

  2. Pokud chcete sestavit edici C# nebo Visual Basic .NET řešení, postupujte podle pokynů v části Sestavení ukázek windows Communication Foundation.

  3. Pokud chcete spustit ukázku v konfiguraci s jedním nebo více počítači, postupujte podle pokynů v části Spuštění ukázek windows Communication Foundation.

Viz také