Хороший Асинхронный шаблон для последовательных запросов WebClient

Большая часть кода, который я написал в.NET для совершения вызовов REST, была синхронна. Так как Silverlight на Windows Phone только поддерживает Асинхронные вызовы WebClient и HttpWebRequest, я задавался вопросом, что хороший асинхронный шаблон для Класса, который выставляет методы, которые выполняют вызовы REST.

Например, у меня есть приложение, которое должно сделать следующее.

  1. Войдите и получите маркер
  2. Используя маркер от № 1, получите список альбомов
  3. Используя маркер от № 1 получают список категорий
  4. и т.д.

мой класс выставляет несколько методов:

  1. Вход в систему ()
  2. GetAlbums ()
  3. GetCategories ()

так как каждый метод должен назвать WebClient с помощью Асинхронных вызовов, что я должен сделать, по существу Вход в систему вызова блока, пока он не возвращается так, чтобы я мог назвать GetAlbums ().

Что хороший путь состоит в том, чтобы пойти об этом в моем классе, который выставляет те методы?

5
задан Omar Shahine 19 March 2010 в 16:29
поделиться

3 ответа

Это действительно зависит от того, что вы хотите делать с этой информацией. Если, например, вы пытаетесь отобразить список альбомов / категорий и т. Д., Один из способов смоделировать это будет

  1. иметь один или несколько классов, которые реализуют интерфейс INotifyPropertyChanged и используются в качестве источников данных для ваших представлений (см. файлы в папке Models в новом PhoneListApplication для примера)
  2. Запустите асинхронную операцию для входа в систему и получения токена, пусть обратный вызов метода async сохранит токен для вас и вызовет функцию, которая запустит асинхронную операцию для получения список альбомов и категорий.
  3. Обратный вызов для асинхронной операции для получения списка альбомов / категорий может обновлять ObservableList (путем добавления в него элементов). Я бы представил, что у вас есть по одному классу для альбомов и категорий, каждая с наблюдаемым списком. В любом случае, как только вы закончите добавление, просто вызовите NotifyPropertyChanged с именем свойства, которое вы изменили, и ваши данные должны появиться.

Существует очевидная проблема со случаями, когда вы хотите подождать и не продолжать, пока не получите что-то обратно по сети (например, если вы хотите сохранить страницу входа в систему до тех пор, пока не узнаете, что вы успешно прошли аутентификацию). В этом случае вы можете просто изменить страницу в асинхронном обратном вызове.

Очевидно, вы также можете сделать что-нибудь более интересное и заставить поток ждать события, установленного функцией обратного вызова async. Я рекомендую не делать этого в потоке пользовательского интерфейса, поскольку он ограничивает вашу возможность иметь такие вещи, как тайм-ауты, и, как правило, очень беспорядок.

3
ответ дан 13 December 2019 в 05:33
поделиться

Вы можете взглянуть на расширения фреймворка Reactive (Rx):

http://www.leading-edge-dev.de/?p=501

http://themechanicalbride.blogspot.com/2009/07/introducing-rx-linq-to-events.html

[edit: ooh - нашел хорошую ссылку:] http://rxwiki.wikidot.com/101samples

Они обеспечивают способ "последовательности" событий, действуя только при выполнении определенных условий - например, допустим, у вас есть метод "AuthenticationResult Authenticate(string user, string pass)"

Вы можете сделать что-то вроде:

var foo = Observable.FromAsyncPattern<string, string, AuthenticationResult>
    (client.BeginAuthenticate, client.EndAuthenticate);
var bar = foo("username","password");
var result = bar.First();

Эффективно превращая асинхронный метод в синхронный. Вы можете расширить это, чтобы включить "цепочку":

var bar = foo("username", "password")
    .Then(authresult => DoSomethingWithResult(authresult));

Отличная штука. :)

7
ответ дан 13 December 2019 в 05:33
поделиться

Мы написали наш уровень службы на стороне клиента со всеми сигнатурами асинхронных функций, которые выглядят следующим образом:

public void MyFunction(
  ArtType arg, 
  Action<ReturnType> success, 
  Action<FailureType> failure);

Код службы выполняет асинхронный вызов веб-службы , и когда это возвращает, он вызывает обратный вызов успеха, если вызов был успешным, и обратный вызов сбоя, если произошла ошибка / исключение. Тогда вызывающий код выглядит примерно так:

MyServiceInstance.MyFunction(
  blahVar,
  returnVal => UIInvoker.Invoke(() => 
    {
      //some success code here
    }),
  fault => UIInvoker.Invoke(() => 
    {
      //some fault handling code here
    }));

(UIInvoker - это просто утилита, которая отправляет обратно в пользовательский интерфейс из фонового потока.)

1
ответ дан 13 December 2019 в 05:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: