Похоже, вы были введены в заблуждение конструктором BitmapImage, который может принимать URL.
Если эта операция действительно достаточно медленная, чтобы оправдать использование шаблона асинхронного ожидания, вам будет гораздо лучше разделить ее на две части.
а) Извлечение данных из URL. Это медленная часть - она связана с IO и больше всего выиграет от async-await.
public static class MyIOAsync
{
public static async Task<byte[]> GetBytesFromUrlAsync(string url)
{
using (var httpClient = new HttpClient())
{
return await httpClient
.GetByteArrayAsync(url)
.ConfigureAwait(false);
}
}
}
б) Создание растрового объекта. Это должно происходить в основном потоке пользовательского интерфейса, и, поскольку в любом случае он относительно быстрый, использование async-await для этой части не имеет смысла.
Предполагая, что вы следуете шаблону MVVM, у вас не должно быть никаких визуальных элементов в слое ViewModel - вместо этого используйте ImageItemVm для каждого требуемого эскиза
public class ImageItemVm : ViewModelBase
{
public ThumbnailItemVm(string url)
{
Url = url;
}
public string Url { get; }
private bool _fetchingBytes;
private byte[] _imageBytes;
public byte[] ImageBytes
{
get
{
if (_imageBytes != null || _fetchingBytes)
return _imageBytes;
// refresh ImageBytes once the data fetching task has completed OK
Action<Task<byte[]>> continuation = async task =>
{
_imageBytes = await task;
RaisePropertyChanged(nameof(ImageBytes));
};
// no need for await here as the continuations will handle everything
MyIOAsync.GetBytesFromUrlAsync(Url)
.ContinueWith(continuation,
TaskContinuationOptions.OnlyOnRanToCompletion)
.ContinueWith(_ => _fetchingBytes = false)
.ConfigureAwait(false);
return null;
}
}
}
Затем можно привязать свойство источника элемента управления Image к свойству ImageBytes соответствующего ImageItemVm - WPF автоматически обработает преобразование из байтового массива в растровое изображение.
Редактировать
Я неправильно понял первоначальный вопрос, но принцип все еще применяется. Мой код, вероятно, все еще будет работать, если вы создадите стартовый файл URL: // но я сомневаюсь, что он будет наиболее эффективным.
Чтобы использовать локальный файл изображения, замените вызов GetBytesFromUrlAsync () этим
public static async Task<byte[]> ReadBytesFromFileAsync(string fileName)
{
using (var file = new FileStream(fileName,
FileMode.Open,
FileAccess.Read,
FileShare.Read,
4096,
useAsync: true))
{
var bytes = new byte[file.Length];
await file.ReadAsync(bytes, 0, (int)file.Length)
.ConfigureAwait(false);
return bytes;
}
}