Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В примере 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 элементов. Это связано с тем, что сетевая привязка, используемая примером, передает данные в сегментах размером четыре килобайта (КБ). Таким образом, клиент получает 4 КБ данных элемента, прежде чем может прочитать хотя бы один элемент. Это нормальное поведение (отправка потоковых данных HTTP в сегментах с разумным размером увеличивает производительность).
Настройка, сборка и запуск примера
Убедитесь, что вы выполнили процедуру настройки One-Time для образцов Windows Communication Foundation.
Чтобы создать версию решения на C# или Visual Basic .NET, следуйте инструкциям по сборке примеров Windows Communication Foundation .
Чтобы запустить пример в конфигурации с одним или несколькими компьютерами, следуйте инструкциям в запуска примеров Windows Communication Foundation.