Megosztás:


Streamelési hírcsatornák – minta

A StreamingFeeds-minta bemutatja, hogyan kezelhetők a nagy mennyiségű elemet tartalmazó szindikációs hírcsatornák. A kiszolgálón a minta bemutatja, hogyan késleltetheti az egyes SyndicationItem objektumok létrehozását a hírcsatornán belül közvetlenül az elem hálózati streambe való írása előtt.

Az ügyfél oldalon a minta bemutatja, hogyan lehet egy egyéni szindikációs hírcsatorna formázót használni a hálózati adatfolyam egyes elemeinek beolvasására, így a beolvasott hírcsatorna soha nincs teljesen pufferelve a memóriába.

A syndication API streamelési képességeinek legjobb bemutatása érdekében ez a minta egy kissé valószínűtlen forgatókönyvet használ, amelyben a kiszolgáló végtelen számú elemet tartalmazó hírcsatornát tesz elérhetővé. Ebben az esetben a kiszolgáló mindaddig új elemeket hoz létre a hírcsatornában, amíg meg nem állapítja, hogy az ügyfél adott számú elemet olvas be a hírcsatornából (alapértelmezés szerint 10). Az egyszerűség kedvéért az ügyfél és a kiszolgáló ugyanabban a folyamatban van implementálva, és egy megosztott ItemCounter objektum használatával nyomon követheti, hogy hány elemet hozott létre az ügyfél. A ItemCounter típus csak azért létezik, hogy lehetővé tegye a mintaforgatókönyv zökkenőmentes befejezését, és nem a bemutatott minta alapvető eleme.

A bemutató Visual C# iterátorokat használ (a yield return kulcsszószerkezet használatával). Az iterátorokról további információt az MSDN "Iteratorok használata" című témakörében talál.

Szolgáltatás

A szolgáltatás egy alapszintű WebGetAttribute szerződést valósít meg, amely egy műveletből áll, ahogyan az az alábbi kódban is látható.

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

A szolgáltatás úgy valósítja meg ezt a szerződést, hogy egy ItemGenerator osztály használatával létrehoz egy potenciálisan végtelen példányfolyamot SyndicationItem egy iterátor használatával, ahogyan az az alábbi kódban látható.

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

    }
    ...
}

Amikor a szolgáltatás implementációja létrehozza a feedet, a ItemGenerator.GenerateItems()-t használja kimenetként az elemek pufferelt gyűjteménye helyett.

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

Ennek eredményeképpen az elemfolyam soha nem lesz teljes mértékben pufferolva a memóriába. Ezt a viselkedést úgy figyelheti meg, hogy beállít egy töréspontot a yield returnItemGenerator.GenerateItems() metóduson belüli utasításra, és megjegyzi, hogy ez a töréspont az első alkalommal jelenik meg, miután a szolgáltatás visszaadta a StreamedFeed() metódus eredményét.

Ügyfél

A mintában szereplő ügyfél egyéni SyndicationFeedFormatter implementációt használ, amely késlelteti a hírcsatorna egyes elemeinek materializálását ahelyett, hogy puffereli őket a memóriába. Az egyéni StreamedAtom10FeedFormatter példányt a következőképpen használja a rendszer.

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

SyndicationFeed feed = formatter.ReadFrom(reader);

A hívás a ReadFrom(XmlReader)-hez normális esetben addig nem tér vissza, amíg a hírcsatorna teljes tartalmát le nem töltötték a hálózatról, és nem pufferelték a memóriába. Az StreamedAtom10FeedFormatter objektum azonban felülírja ReadItems(XmlReader, SyndicationFeed, Boolean) , hogy pufferelt gyűjtemény helyett iterátort adjon vissza, ahogy az az alábbi kódban is látható.

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

Az eredmény az, hogy egyetlen elemet sem olvas be a hálózatról, amíg az ügyfélalkalmazás, amely bejárja az ReadItems() eredményeit, nem áll készen a használatára. Ezt a viselkedést úgy figyelheti meg, hogy beállít egy töréspontot az yield return utasításon belül StreamedAtom10FeedFormatter.DelayReadItems() , és megfigyeli, hogy ez a töréspont a hívás ReadFrom() befejezése után először jelenik meg.

Az alábbi utasítások bemutatják, hogyan hozhatja létre és futtathatja a mintát. Vegye figyelembe, hogy bár a kiszolgáló nem hoz létre elemeket, miután az ügyfél 10 elemet olvasott, a kimenet azt mutatja, hogy az ügyfél jelentősen több mint 10 elemet olvas be. Ennek az az oka, hogy a minta által használt hálózati kötés négy kilobájtos (KB) szegmensekben továbbítja az adatokat. Így az ügyfél 4 KB tételadatokat kap, mielőtt még egy elemet is beolvashat. Ez normális viselkedés (a streamelt HTTP-adatok ésszerűen nagy méretű szegmensekben való küldése növeli a teljesítményt).

A példa beállítása, elkészítése és futtatása

  1. Győződjön meg arról, hogy elvégezte a Windows Communication Foundation-minták One-Time beállítási eljárását.

  2. A megoldás C# vagy Visual Basic .NET kiadásának létrehozásához kövesse Windows Communication Foundation-mintákcímű témakör utasításait.

  3. Ha a mintát egy vagy több gép közötti konfigurációban szeretné futtatni, kövesse A Windows Communication Foundation-minták futtatásacímű témakör utasításait.

Lásd még