2013-01-31 5 views
5

J'ai une bibliothèque de classes portable (PCL) ciblée sur Profile158 (Windows Store, .NET 4.5, Silverlight 5, Windows Phone 8). Je peux facilement travailler avec des méthodes qui retournent un type de tâche, et tout fonctionne comme je m'y attends. Chaque fois que j'accède à la propriété Result, il termine l'exécution du code asynchrone et renvoie le résultat. Cependant, si j'utilise les mots-clés async/await dans une méthode à l'intérieur de la PCL, je récupère une tâche. Toutefois, lorsque j'essaie d'accéder à la propriété Result, il bloque et ne retourne jamais.Utilisation de Microsoft.bcl.async en PCL avec Mono Droid?

regardant la fenêtre de sortie de débogage dans Visual Studio dans les deux cas, je vois le même texte:

Thread started: 
Thread started: 
Loaded assembly: Mono.Security.dll [External] 
Thread started: 
Thread started: 

Il apparaît donc comme si le code est en cours d'exécution, mais il ne revient jamais au thread d'interface utilisateur. Est-ce que quelqu'un d'autre a essayé d'utiliser un PCL avec Microsoft.bcl.async dans le PCL?

Mon projet Mono Droid est destiné à Android 2.1.

Merci, - John

Mise à jour:
Voici quelques informations supplémentaires sur les différents scénarios. Tout d'abord, voici le code qui ne fonctionne sur Mono Droid lorsqu'il est écrit dans le code de l'interface utilisateur:

var task = request.GetResponseAsync(); 
string html = task.Result.GetResponseText(); 

J'ai ensuite créé la méthode suivante dans la PCL:

public async Task<string> Test() 
{ 
    IHttpResponse responce = await GetResponseAsync(); 
    return responce.GetResponseText(); 
} 

Et appelez avec ce code de la mono code de l'interface utilisateur:

string html = request.Test().Result; 

retourne jamais ...

+0

Si vous utilisez la propriété Result, cela bloquera jusqu'à la fin de la tâche. Si vous faites cela à partir du même thread où la tâche elle-même doit s'exécuter, vous vous êtes essentiellement donné une impasse. Ce n'est pas du tout clair sur ce que fait votre code en ce moment ... avez-vous un programme court mais complet démontrant le problème? –

+0

@dsplaisted utilisé cette couche avec MonoDroid lors de sa démo à BUILD - http://channel9.msdn.com/Events/Build/2012/3-004 - Je vais ajouter l'étiquette PCL à ce poste et mettre un signal de chauve-souris - il sera là pendant les heures de Redmond ... – Stuart

+0

Non lié à votre question, mais Microsoft.Bcl.Async est encore en version bêta. L'utiliser dans n'importe quel code de production doit être évité. Bien sûr, vous pourriez juste le tester en ce moment. –

Répondre

3

C'est un classic deadlock scenario, un s Je décris sur mon blog. Par défaut, await capture un "contexte" et l'utilise pour reprendre la méthode async. Ce "contexte" est le SynchronizationContext actuel à moins qu'il ne soit null, auquel cas il s'agit de l'actuel TaskScheduler. Par conséquent, vous appelez une méthode async à partir d'un thread d'interface utilisateur (qui fournit un SynchronizationContext), puis en bloquant le thread d'interface utilisateur en appelant Result. La méthode async ne peut pas terminer car il essaie de terminer sur le thread d'interface utilisateur qui est bloqué.

Pour résoudre ce problème, procédez comme suit:

  1. Utilisez async tout le long. Ne pas appeler Result ou Wait sur Task s retourné à partir de async méthodes; utilisez await à la place. Utilisez ConfigureAwait(false) autant que possible dans votre code de bibliothèque.

Vous pouvez également trouver mon async/await intro utile.

+0

Je suis OK avec le blocage du code de l'interface utilisateur jusqu'à la fin de l'opération. Le problème est qu'il ne finit jamais et ne retourne jamais au thread UI. Si je renvoie une tâche de ma méthode et n'utilise pas async/await, le code d'interface utilisateur bloque brièvement, puis retourne. J'ai essayé le même code d'interface utilisateur avec Windows Phone 8 et l'application Windows Store, et ils retournent tous les deux correctement dans le thread d'interface utilisateur. J'ai également vérifié que SynchronizationContext n'est pas nul dans Android, et ce n'est pas le cas. Il y a donc quelque chose à propos d'Android et de PCL qui utilisent async/await qui semble causer le problème. –

+0

Cette même impasse existe dans toutes les interfaces utilisateur, y compris WP8 et netcore. Si vous avez du code qui utilise 'Result' sur une méthode' async' dans WP8 sans deadlock et les mêmes interblocages de code * exact * dans Android, alors postez le code. –

+0

Je viens de poster le code. –

Questions connexes