[IronPython] : IronPython & Silverlight 2 - Part I
Dans le présent billet, je vais aborder une manière de récupérer un flux dans Silverlight de manière asynchrone et de mettre à jour l'UI (grâce à IronPython, mais ça vous l'aviez déjà compris ;)).
1 - Récupération du flux:
Pour ce faire, vous avez à votre disposition la méthode HttpWebRequest.BeginGetResponse.
signature --> public IAsyncresult BeginGetResponse(AsyncCallback, Object)
Voici le code qui la met en oeuvre :
import clr
clr.AddReference("IronPython")
from System.Windows import Application
from System.Windows.Controls import UserControl
class App:
def __init__(self):
self.scene = Application.Current.LoadRootVisual(UserControl(), "app.xaml")
def start(self):
self.getDatas()
def getDatas(self):
from System import Uri, AsyncCallback
endPoint = Uri("url")
from System.Net import WebRequest
request = WebRequest.Create(endPoint) #création de la requête
request.BeginGetResponse(AsyncCallback(self.readCallback), request)
def readCallback(self, result):
request = result.AsyncState #récupération de la requête
response = request.EndGetResponse(result) #récupération de la réponse
from System.Net import HttpStatusCode
if response.StatusCode == HttpStatusCode.OK: #test du statut
stream = response.GetResponseStream() #récupération du flux
#Mise à jour de l'UI
...
App().start()
2 - Mise à jour de l'UI
A ce moment, nous avons récupéré le flux depuis notre url (webservice ou autre...), mais nous ne pouvons pas modifier l'interface. En effet, nous ne sommes plus dans le 'Main Thread' et toute tentative de mise à jour directe sera bloquée.
Pour ce faire il nous faut utiliser un Dispatcher et sa méthode BeginInvoke comme suit:
self.scene.Dispatcher.BeginInvoke(...)
La méthode BeginInvoke attend un delegate et un object[] en paramètre. comment y arriver avec IronPython?
3 - delegate
Si vous avez introspecté la dll IronPython à l'aide de reflector, vous êtes certainement tombé sur ce qui nous sera très utile dans le cas qui nous intéresse ici. il s'agit du wrapper CallTarget1 (namespace IronPython.Runtime.Calls) qui nous retourne un delegate :)
Nous avons donc :
def readCallback(self, result):
request = result.AsyncState #récupération de la requête
response = request.EndGetResponse(result) #récupération de la réponse
from System.Net import HttpStatusCode
if response.StatusCode == HttpStatusCode.OK: #test du statut
stream = response.GetResponseStream() #récupération du flux from IronPython.Runtime import Calls
self.scene.Dispatcher.BeginInvoke(Calls.CallTarget1(self.update), stream)
def update(self, stream):
from System.IO import StreamReader
reader = StreamReader(stream)
#... mise à jour
reader.Close()
Pour les modifications de l'interface, à vous de jouer ;)
il est également possible d'utilser la méthode DownloadStringAsync.
A plus.
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :