Ошибка, которую некоторые совершают, состоит в том, что они могут оставить неизменным свой синхронный код (в вашем случае код, который ожидает, что сможет вызвать функцию, которая возвращает изображение) и каким-то образом просто сделать его частьюсправиться с тем, чтобы быть асинхронным.Это просто невозможно, поскольку функция, вызываемая вашим кодом, должна стать асинхронной, как и сам вызывающий код, так же как и код, вызывающий этот код, и т. Д. Вплоть до любого события, инициировавшего код.
Новые возможности языка C # на горизонте призваны облегчить эту ситуацию, но в данный момент они вам недоступны.Все равно потребуется весь код в цепочке, чтобы понять, что он асинхронный.
Я часто вижу, что Reactive рекламируется как решение такого рода проблемы, однако Reactive на самом деле не предназначен для решения этой проблемы, и выв конечном итоге прыгаю через некоторые уродливые обручи, пытаясь заставить его работать.
Поэтому я предлагаю решение, которое я использую в качестве блога здесь .С этим кодом (и он требует удивительно короткого количества кода, добавленного в проект) ваш код может быть записан как: -
IEnumerable<AsyncOperation> GetPicture(Uri uri, Action<ImageSource> returnResult)
{
WebRequest req = WebRequest.Create(uri)
Stream pictureStream = null;
yield return req.GetRequestStreamAsyncOp(r =>
{
try {reqStream = r; } catch { }
});
yield return AsyncOperationService.SwitchToUIThread();
if (pictureStream != null)
{
var picture = new BitmapImage();
picture.SetSource(picture);
returnResult(picture);
}
else
{
//Picture is unavailable
//returnResult(someOtherPicure);
}
}
Ваш вызывающий код будет выглядеть так: -
GetPicture(_uri, picture =>
{
//Do stuff with your picture here.
}).Run(err =>
{
if (err != null)
{
//Oops something bad happened code here.
}
});