Async / waiting for deadlock while loading images

I am developing a Windows Phone 8.1 application. I have a screen with a list of news titles with thumbnails.

First I make an asynchronous HTTP request to get the news collection in JSON (satisfying the 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; } } 

news

 public class News : ObservableObject { ... public string Title { get; set; } public string ImagePath { get; set; } } 

This works fine so far, but as soon as I get the ImagePath property, I would like to load and display this image. I found a solution for this asynchronously here: WP 8.1 Linking the image to the http request - so that with xaml getting the path to the image, it calls the converter class ( BinaryToImageSourceConverter ), also using the NotifyTaskCompletion template.

The problem occurs in the following method:

 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; } 

When the first await is called, the debugger never reaches the next line, and the method never returns. The variable string path has the correct content.

So far, I have tried to use ConfigureAwait(false) , but in my case this does not work.

I also found out in the topic: Deadlock when using async expects that:

When you use ConfigureAwait(false) , you tell your program that you don't mind the context. It can solve some deadlock problems, but usually this is not the right solution. The correct solution, most likely, will never wait for tasks in blocking mode and be asynchronous to the end.

I do not know where I could block this material. What could be causing this impasse?

And if all about the wrong approach, do you know any template that is more suitable for loading sketches into a collection of items?

Thank you for your help.


update: how GetImage is called: as in the subject: WP 8.1 Linking an image to an 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; } } } 

and in xaml:

 <Image DataContext="{Binding ImagePath, Converter={StaticResource WebPathToImage}}" Source="{Binding Result}" Stretch="UniformToFill" Height="79" Width="79"/> 
+6
source share
2 answers

First, if you are using Windows Phone 8.1, it is recommended that you use the HttpClient from the Windows.Web.Http namespace and not from System.Net.Http . Some reasons are explained on this link .

My answer uses the new Windows.Web.Http.HttpClient , so your GetImage method might look like this:

  private async Task<BitmapImage> GetImage(string path) { using (var webCLient = new Windows.Web.Http.HttpClient()) { webCLient.DefaultRequestHeaders.Add("User-Agent", "bot"); var responseStream = await webCLient.GetBufferAsync(new Uri(path)); var memoryStream = new MemoryStream(responseStream.ToArray()); memoryStream.Position = 0; var bitmap = new BitmapImage(); await bitmap.SetSourceAsync(memoryStream.AsRandomAccessStream()); return bitmap; } } 

I tested this method on a sample URL and it displayed correctly in the Image control.

Secondly, why don't you just let the Image control descriptor load BitmapImage without a converter so that your XAML looks like this:

 <Image Source="{Binding ImagePath}" Stretch="UniformToFill" Height="79" Width="79" /> 

Thus, your ImagePath can be a path to a resource from the Internet and a local resource.

0
source

Try maybe calling GetImage in Task.Factory.Run to make the task execute another thread.

Attention to creating a bitmap can be a problem because the bitmap is not created in the user interface stream.

0
source

All Articles