L’idée de base est la suivante: j’ai un web service à appeler mais je veux attendre le résultat. Hors en Silverlight pour WP7, tous les appels sont asynchrones et sont basés sur un pattern évènementiel:
private void LogToCollectoOnlineServices()
{
UserServiceSoapClient userServiceSoapClient = new UserServiceSoapClient();
userServiceSoapClient.GetStateCompleted +=
userServiceSoapClient_GetStateCompleted;
userServiceSoapClient.GetStateAsync(Account.ID);
}
void userServiceSoapClient_GetStateCompleted(object sender,
GetStateCompletedEventArgs e)
{
}
Donc la, pas bête je me dis : mettons un ManualResetEvent :
private void LogToCollectoOnlineServices()
{
using (ManualResetEvent evt = new ManualResetEvent(false))
{
UserServiceSoapClient userServiceSoapClient = new UserServiceSoapClient();
userServiceSoapClient.GetStateCompleted +=
userServiceSoapClient_GetStateCompleted;
userServiceSoapClient.GetStateAsync(Account.ID, evt);
evt.WaitOne();
evt.Close();
}
}
void userServiceSoapClient_GetStateCompleted(object sender,
GetStateCompletedEventArgs e)
{
((ManualResetEvent) e.UserState).Set();
}
Et paf, je vous le donne en mille, ca ne marche pas! En effet, ici le GetStateCompleted n’est jamais appelé.
L’explication est la suivante : Silverlight pour WP7 (comme Silverlight) passe par le thread de l’UI pour lancer ses requêtes réseaux. Or ici, avec mon evt.WaitOne(), je bloque le thread principal et donc ce dernier ne peut pas dispatcher les ordres réseaux et donc ma requête web ne part pas
.
Donc en conclusion, le pattern d’asynchronisme est à respecter à la lettre! Ici la solution passera par une gestion différente avec par exemple un évènement levé lorsque la requête a fini pour mettre à jour mon interface.
.Net, Silverlight, Windows Phone
Windows Phone 7