I have a Windows 8 app that I'm attempting to load an image using the following code:
private async Task<BitmapImage> LoadImage(IStorageFile storageFile)
{
System.Diagnostics.Debug.WriteLine("LoadImage started");
try
{
// Set the image source to the selected bitmap
BitmapImage bitmapImage = null;
// Ensure a file was selected
if (storageFile != null)
{
System.Diagnostics.Debug.WriteLine("LoadImage::OpenAsync");
// Ensure the stream is disposed once the image is loaded
using (IRandomAccessStream fileStream = await storageFile.OpenAsync(Windows.Storage.FileAccessMode.Read))
{
System.Diagnostics.Debug.WriteLine("New Bitmap");
// Set the image source to the selected bitmap
bitmapImage = new BitmapImage();
System.Diagnostics.Debug.WriteLine("Set Source");
bitmapImage.SetSource(fileStream);
}
}
return bitmapImage;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
} // End of catch
finally
{
System.Diagnostics.Debug.WriteLine("Load image finished");
}
return null;
}
When I run the code it sometimes works. But other times it simply hangs and I get the following output:
LoadImage started LoadImage::OpenAsync
Am I using storageFile.OpenAsAsync
incorrectly? My storage file is the result of a call to:
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.List;
openPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
openPicker.FileTypeFilter.Add(".jpg");
openPicker.FileTypeFilter.Add(".png");
openPicker.FileTypeFilter.Add(".bmp");
StorageFile file = await openPicker.PickSingleFileAsync();
if (file != null)
{
var loadImageTask = LoadImage(currentStorageFile);
loadImageTask.Wait();
DisplayImage.Source = loadImageTask.Result;
}
So it should not be a sandbox issue (and there is no exception).
Could anyone point me in the right path?
The call to Task.Wait
and Task.Result
is causing the deadlock. I explain this in detail on my blog and in a recent MSDN article.
In short, when you await
a Task
that has not yet completed, by default it will capture a "context" and use that to resume the async
method. In your case, this is the UI context. However, when you call Wait
(or Result
), you're blocking the UI thread, so the async
method cannot complete.
To fix this, use await
instead of Wait
/Result
, and use ConfigureAwait(false)
everywhere you can.