Sto sviluppando un'applicazione Windows Phone 8.1. Ho uno schermo con una lista di titoli di notizie con miniature.Asincrono/attendi deadlock durante il download delle immagini
Prima sto facendo richiesta HTTP asincrona per ottenere raccolta notizie in JSON (soddisfare il NotifyTaskCompletion
pattern)
NewsCategories = new NotifyTaskCompletion<ObservableCollection<NewsCategory>>(_newsService.GetNewsCategoriesAsync());
NewsCategory:
public class NewsCategory : ObservableObject
{
...
public string Title { get; set; }
public ObservableCollection<News> Items { get; set; }
}
Notizie:
public class News : ObservableObject
{
...
public string Title { get; set; }
public string ImagePath { get; set; }
}
Finora funziona perfettamente, ma non appena avrò la proprietà ImagePath
, vorrei scaricare e visualizzare l'immagine fornita. Ho trovato una soluzione per farlo in modo asincrono qui: WP 8.1 Binding image from a http request - in modo che quando xaml ottiene il percorso dell'immagine, chiama una classe di convertitore (BinaryToImageSourceConverter
), utilizzando anche il modello NotifyTaskCompletion
.
Il problema si verifica nel seguente metodo:
private async Task<BitmapImage> GetImage(string path)
{
HttpClient webCLient = new HttpClient();
var responseStream = await webCLient.GetStreamAsync(path);
var memoryStream = new MemoryStream();
await responseStream.CopyToAsync(memoryStream);
memoryStream.Position = 0;
var bitmap = new BitmapImage();
await bitmap.SetSourceAsync(memoryStream.AsRandomAccessStream());
return bitmap;
}
Quando il primo await
si chiama, il debugger non raggiungono mai la riga successiva e il metodo non ritorna mai. La variabile string path
ha un contenuto adeguato.
Finora ho provato a utilizzare ConfigureAwait(false)
, ma nel mio caso non funziona.
ho trovato anche in tema: Deadlock while using async await, che:
Quando si utilizza
ConfigureAwait(false)
, dite al vostro programma non vi dispiace sul contesto. Può risolvere alcuni problemi di stallo, ma di solito non è la soluzione giusta. La soluzione giusta probabilmente non attenderà mai le attività in modo bloccante e sarà completamente asincrona.
Non so dove potrei avere quella roba in un modo bloccante. Quale può essere la ragione per questo punto morto?
E se si tratta di un approccio errato, conosci qualche schema che sarebbe più appropriato per scaricare le miniature in una raccolta di elementi?
Grazie per il vostro aiuto.
aggiornamento: come è GetImage
invocato: E 'come in argomento: WP 8.1 Binding image from a http request
public class WebPathToImage : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value == null) return null;
return new NotifyTaskCompletion<BitmapImage>(GetImage((String)value));
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{ throw new NotImplementedException(); }
private async Task<BitmapImage> GetImage(string path)
{
using (var webCLient = new HttpClient())
{
webCLient.DefaultRequestHeaders.Add("User-Agent", "bot");
var responseStream = await webCLient.GetStreamAsync(path).ConfigureAwait(false);
var memoryStream = new MemoryStream();
await responseStream.CopyToAsync(memoryStream);
memoryStream.Position = 0;
var bitmap = new BitmapImage();
await bitmap.SetSourceAsync(memoryStream.AsRandomAccessStream());
return bitmap;
}
}
}
e in XAML:
<Image
DataContext="{Binding ImagePath, Converter={StaticResource WebPathToImage}}"
Source="{Binding Result}"
Stretch="UniformToFill"
Height="79" Width="79"/>
Come viene richiamato 'GetImage'? Oppure lo blocchi usando '.Result' o' .Wait'? –
Ho modificato il mio post per mostrare il codice. –
Non vedo direttamente nulla che possa essere sbagliato. Se potessi fare una piccola, minima riproduzione di questo, sarebbe di grande aiuto. –