2013-01-31 15 views
5

Possiedo una libreria di classi portatile (PCL) indirizzata a Profile158 (Windows Store, .NET 4.5, Silverlight 5, Windows Phone 8). Posso facilmente lavorare con metodi che restituiscono un tipo di attività, e tutto funziona come mi aspetterei. Ogni volta che accedo alla proprietà Result, termina l'esecuzione del codice asincrono e restituisce il risultato.Utilizzo di Microsoft.bcl.async in PCL con Mono Droid?

Tuttavia, se utilizzo le parole chiave asincrone/attese in un metodo all'interno del PCL, viene restituito un compito. Tuttavia, quando tento di accedere alla proprietà Result, blocca e non restituisce mai.

Guardando la finestra di output di debug in Visual Studio in entrambi i casi che vedo lo stesso testo:

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

Così sembra come se il codice viene eseguito, ma non è mai torna al thread UI. Qualcun altro ha provato a utilizzare un PCL con Microsoft.bcl.async nel PCL?

Il mio progetto Mono Droid è destinato a Android 2.1.

Grazie, - John

Aggiornamento:
Ecco alcune ulteriori informazioni sui diversi scenari. In primo luogo, qui è il codice che funziona su Mono Droid quando scritto nel codice di interfaccia utente:

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

Poi ho creato il seguente metodo nel PCL:

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

e chiamarlo con questo codice dal Mono codice UI:

string html = request.Test().Result; 

che non restituisce mai ...

+0

Se si utilizza la proprietà Result, questa verrà bloccata fino al completamento dell'attività. Se lo fai dallo stesso thread in cui l'attività stessa deve essere eseguita, ti sei praticamente dato un deadlock. Non è affatto chiaro cosa fa il tuo codice in questo momento ... hai un programma breve ma completo che mostri il problema? –

+0

@dsplaisted ha usato questo livello con MonoDroid durante la sua dimostrazione a BUILD - http://channel9.msdn.com/Events/Build/2012/3-004 - Aggiungerò il tag PCL a questo post e metto fuori un segnale bat - sarà presente durante le ore di Redmond ... – Stuart

+0

Non correlato alla tua domanda, ma Microsoft.Bcl.Async è ancora beta. Dovrebbe essere evitato l'uso in qualsiasi codice di produzione. Certo, potresti testarlo proprio adesso. –

risposta

3

Questo è un classic deadlock scenario, un s che descrivo sul mio blog.

Per impostazione predefinita, await acquisisce un "contesto" e lo utilizza per riprendere il metodo async. Questo "contesto" è l'attuale SynchronizationContext a meno che non sia null, nel qual caso è l'attuale TaskScheduler.

Quindi, si sta chiamando un metodo async da un thread dell'interfaccia utente (che fornisce un SynchronizationContext), quindi si blocca il thread dell'interfaccia utente chiamando Result. Il metodo async non può essere completato perché sta tentando di terminare sul thread dell'interfaccia utente, che è bloccato.

Per risolvere questo problema, seguire queste indicazioni:

  1. Usa async fino in fondo. Non chiamare Result o Wait su Task s restituiti dai metodi async; utilizzare invece await.
  2. Utilizzare ConfigureAwait(false) quando possibile nel codice della libreria.

Si può anche trovare il mio async/await intro utile.

+0

Sto bene con il blocco del codice UI fino al completamento dell'operazione. Il problema è che non finisce mai e non torna mai al thread dell'interfaccia utente. Se restituisco un Task dal mio metodo e non utilizzo async/await, il codice UI blocca brevemente, quindi restituisce. Ho provato lo stesso esatto codice UI con Windows Phone 8 e l'app di Windows Store, ed entrambi ritornano correttamente al thread dell'interfaccia utente. Ho anche verificato che SynchronizationContext non sia nullo in Android, e non lo è. Quindi c'è qualcosa su Android e PCL che usano async/attendi che sembra causare il problema. –

+0

Questo stesso deadlock esiste in tutte le interfacce utente, inclusi WP8 e netcore. Se hai codice che utilizza 'Result' su un metodo' async' in WP8 senza deadlock e lo stesso * esatto * deadlock del codice in Android, inserisci il codice. –

+0

Ho appena pubblicato il codice. –

Problemi correlati