Pregunta

La mayor parte del código que he escrito en .NET para realizar llamadas resto han sido sincrónica. Desde Silverlight en Windows Phone sólo soporta asíncrono cliente Web y HttpWebRequest llama, me preguntaba lo que es un buen patrón asincrónico es para una clase que expone métodos que realizan llamadas REST.

Por ejemplo, tengo una aplicación que tiene que hacer lo siguiente.

  1. Identificación y obtener símbolo
  2. Uso de token del # 1, obtener una lista de los álbumes
  3. Uso de token del # 1 obtener una lista de categorías
  4. etc.

mi clase expone algunos métodos:

  1. Inicio de sesión ()
  2. GetAlbums ()
  3. GetCategories ()

ya que cada método tiene que llamar cliente Web utilizando asíncrono llama lo que tengo que hacer es esencialmente bloque de llamada de sesión hasta que se vuelve de modo que pueda llamar GetAlbums ().

¿Qué es una buena manera de ir sobre esto en mi clase que exponga esos métodos?

¿Fue útil?

Solución

Realmente depende de lo que quiere hacer con esta información. Si por ejemplo usted está tratando de mostrar la lista de álbumes / categorias, etc, una forma de modelar esto sería

  1. Tener una o más clases que implementa la interfaz INotifyPropertyChanged, y se utilizan como fuentes de datos para sus puntos de vista (mirar los archivos en la carpeta Modelos en una nueva PhoneListApplication para un ejemplo)
  2. Iniciar una operación asincrónica para entrar y obtener el token, tiene tienda de devolución de llamada del método asíncrono el token para usted y llamar a una función que se iniciará una operación asincrónica para obtener la lista de álbumes y categorías.
  3. La llamada de retorno para la operación asincrónica para obtener una lista de los álbumes / categorías pueden actualizar un ObservableList (mediante la adición de elementos a ella). Yo por imágenes que haya una clase cada uno de los álbumes y categorías, cada una con una lista observable. De todas formas, una vez que haya terminado de añadir, simplemente llame NotifyPropertyChanged con el nombre de la propiedad ha cambiado, y los datos deben aparecer.

Hay un problema evidente con los casos en los que desee esperar y no continúe hasta que reciba algo a través de la red (por ejemplo, si desea mantener la página de inicio de sesión alrededor hasta que sabe que ha autenticado correctamente). En este caso sólo podría cambiar la página en la devolución de llamada asincrónica.

Se podría, obviamente, también hacer algo más elegante y tienen una espera de rosca para un evento establecido por la devolución de llamada asincrónica. Yo recomiendo no tengo el hilo de interfaz de usuario hacer esto, ya que limita su capacidad para tener cosas como los tiempos de espera, y en general es muy desordenado.

Otros consejos

Es posible echar un vistazo a la reactiva (Rx) extensiones marco:

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

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

[editar: ooh - encontrado un buen enlace:] http://rxwiki.wikidot.com/101samples

Ellos proporcionan una forma de eventos "secuencia", que actúan únicamente en ciertas condiciones se reunieron - por ejemplo, decir que tenía un método "AuthenticationResult la autenticación (usuario cadena, pase cadena)"

Se podría hacer algo como:

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

convirtiendo efectivamente un método asíncrono a uno síncrona. Se puede extender esto para incluir "encadenamiento":

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

cosas muy buenas. :)

Escribimos nuestra capa de servicio del lado del cliente con todas las firmas de función asíncrona que se ven así:

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

El código de servicio hace una llamada asíncrona al servicio web, y cuando eso vuelve llama a la devolución de llamada de éxito si la llamada se ha realizado correctamente, y la devolución de llamada fracaso si hubo un fallo / excepción. A continuación, el código de llamada poco se parece a esto:

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

(UIInvoker es sólo una utilidad que envía de vuelta a la interfaz de usuario de un hilo de fondo.)

Me armar algo que es un poco más fluido.

reparador en Silverlight es una biblioteca que he creado para ayudar tanto con Silverlight y WP7.

código

He incluido a continuación para mostrar cómo se puede utilizar la biblioteca para recuperar tweets de Twitter.

Uso de muestra de Restful-Silverlight Tweets de recuperar de Twitter:


//silverlight 4 usage
List<string> tweets = new List<string>();
var baseUri = "http://search.twitter.com/";

//new up asyncdelegation
var restFacilitator = new RestFacilitator();
var restService = new RestService(restFacilitator, baseUri);
var asyncDelegation = new AsyncDelegation(restFacilitator, restService, baseUri);

//tell async delegation to perform an HTTP/GET against a URI and return a dynamic type
asyncDelegation.Get<dynamic>(new { url = "search.json", q = "#haiku" })
    //when the HTTP/GET is performed, execute the following lambda against the result set.
    .WhenFinished(
    result => 
    {
        textBlockTweets.Text = "";
        //the json object returned by twitter contains a enumerable collection called results
        tweets = (result.results as IEnumerable).Select(s => s.text as string).ToList();
        foreach (string tweet in tweets)
        {
             textBlockTweets.Text += 
             HttpUtility.HtmlDecode(tweet) + 
             Environment.NewLine + 
             Environment.NewLine;
        }
    });

asyncDelegation.Go();

//wp7 usage
var baseUri = "http://search.twitter.com/";
var restFacilitator = new RestFacilitator();
var restService = new RestService(restFacilitator, baseUri);
var asyncDelegation = new AsyncDelegation(restFacilitator, restService, baseUri);

asyncDelegation.Get<Dictionary<string, object>>(new { url = "search.json", q = "#haiku" })
               .WhenFinished(
               result =>
               {
                   List<string> tweets = new List();
                   textBlockTweets.Text = "";
                   foreach (var tweetObject in result["results"].ToDictionaryArray())
                   {
                       textBlockTweets.Text +=
                           HttpUtility.HtmlDecode(tweetObject["text"].ToString()) + 
                           Environment.NewLine + 
                           Environment.NewLine;
                   }
               });

asyncDelegation.Go();

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top