스트리밍 피드 샘플
StreamingFeeds 샘플은 많은 수의 항목이 포함된 신디케이션 피드를 관리하는 방법을 보여 줍니다. 서버에서 이 샘플은 항목을 네트워크 스트림에 쓰기 바로 전까지 피드 내에 개별 SyndicationItem 개체를 만드는 동작을 지연시키는 방법을 보여 줍니다.
클라이언트에서 이 샘플은 사용자 지정 배포 피드 포맷터를 사용하여 읽고 있는 피드가 메모리에 완전히 버퍼링되지 않도록 네트워크 스트림에서 개별 항목을 읽을 수 있는 방법을 보여 줍니다.
배포 API의 스트리밍 기능을 가장 잘 보여 주기 위해 이 샘플에서는 서버가 매우 많은 수의 항목이 포함된 피드를 노출하는 경우와 같이 실제로 드문 시나리오를 사용합니다. 이 경우 서버는 클라이언트가 피드에서 지정된 수의 항목(기본값: 10개)을 읽었다고 확인할 때까지 계속해서 피드에 새 항목을 생성합니다. 단순성을 위해 클라이언트와 서버는 모두 동일한 프로세스로 구현되며 공유 ItemCounter
개체를 사용하여 클라이언트가 생성한 항목의 수를 추적합니다. ItemCounter
형식은 샘플 시나리오를 간단히 종료할 목적으로만 사용되며 설명하려는 패턴의 핵심 요소는 아닙니다.
데모에서는 Visual C# 반복기를 사용합니다(yield return
키워드 구성 사용). 반복기에 대한 자세한 내용은 MSDN의 "반복기 사용" 항목을 참조하세요.
서비스
이 서비스는 다음 코드에서와 같이 하나의 작업으로 구성된 기본 WebGetAttribute 계약을 구현합니다.
[ServiceContract]
interface IStreamingFeedService
{
[WebGet]
[OperationContract]
Atom10FeedFormatter StreamedFeed();
}
이 서비스는 다음 코드에서와 같이 ItemGenerator
클래스에서 반복기를 사용하여 SyndicationItem 인스턴스의 무한 스트림을 만드는 방식으로 이 계약을 구현합니다.
class ItemGenerator
{
public IEnumerable<SyndicationItem> GenerateItems()
{
while (counter.GetCount() < maxItemsRead)
{
itemsReturned++;
yield return CreateNextItem();
}
}
...
}
서비스 구현에서 피드를 만들면 버퍼링된 항목 컬렉션 대신 ItemGenerator.GenerateItems()
의 출력이 사용됩니다.
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();
}
결과적으로 항목 스트림은 메모리에 완전히 버퍼링되지 않습니다. yield return
문의 ItemGenerator.GenerateItems()
메서드 내부에 중단점을 설정하고 서비스가 StreamedFeed()
메서드의 결과를 반환한 후 처음으로 이 중단점이 발생하는 것을 보고 이 동작을 확인할 수 있습니다.
클라이언트
이 샘플의 클라이언트는 피드에 있는 개별 항목을 메모리에 버퍼링하는 대신 이 항목의 구체화를 지연시키는 사용자 지정 SyndicationFeedFormatter 구현을 사용합니다. 사용자 지정 StreamedAtom10FeedFormatter
인스턴스는 다음과 같이 사용됩니다.
XmlReader reader = XmlReader.Create("http://localhost:8000/Service/Feeds/StreamedFeed");
StreamedAtom10FeedFormatter formatter = new StreamedAtom10FeedFormatter(counter);
SyndicationFeed feed = formatter.ReadFrom(reader);
일반적으로 네트워크에서 피드의 전체 콘텐츠를 읽고 메모리에 버퍼링할 때까지는 ReadFrom(XmlReader)에 대한 호출이 반환되지 않습니다. 반면 StreamedAtom10FeedFormatter
개체는 다음 코드에서와 같이 ReadItems(XmlReader, SyndicationFeed, Boolean)를 재정의하고 버퍼링된 컬렉션 대신 반복기를 반환합니다.
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();
}
따라서 ReadItems()
의 결과를 이동하는 클라이언트 애플리케이션에서 사용 준비를 마칠 때까지는 네트워크에서 각 항목을 읽지 않습니다. yield return
문의 StreamedAtom10FeedFormatter.DelayReadItems()
내부에 중단점을 설정하고 ReadFrom()
에 대한 호출이 완료된 후에 처음으로 이 중단점이 발생하는 것을 보고 이 동작을 확인할 수 있습니다.
다음 지침에서는 샘플을 빌드하고 실행하는 방법을 보여 줍니다. 클라이언트에서 10개의 항목을 읽고 나면 서버에서 항목 생성을 중지하지만 출력에는 클라이언트에서 10개 항목보다 훨씬 많은 항목을 읽는 것으로 표시됩니다. 이는 샘플에서 사용되는 네트워킹 바인딩에서 데이터를 4KB 단위의 세그먼트로 전송하기 때문입니다. 따라서 클라이언트는 한 항목을 읽을 기회가 생기기도 전에 4KB의 항목 데이터를 받습니다. 이는 정상적인 동작입니다. 스트리밍된 HTTP 데이터를 적절한 크기의 세그먼트로 보내면 성능이 향상됩니다.
샘플을 설치, 빌드 및 실행하려면
Windows Communication Foundation 샘플의 일회 설치 절차를 수행했는지 확인합니다.
C# 또는 Visual Basic .NET 버전의 솔루션을 빌드하려면 Building the Windows Communication Foundation Samples의 지침을 따릅니다.
단일 컴퓨터 또는 다중 컴퓨터 구성에서 샘플을 실행하려면 Windows Communication Foundation 샘플 실행의 지침을 따릅니다.