Развертывание асинхронной операции и ее асинхронного обратного вызова в TaskCompletionSource
У меня есть метод в сервисе, который вызывается моей моделью представления для получения изображения. Изображение извлекается из внешней библиотеки (iOS API в Xamarin), которая использует механизм обратного вызова вместо ожидания.
Чтобы сделать мой метод приемлемым, я обертываю метод в TaskCompletionSource. Хотя проблема в обратном вызове API, мне нужно вызвать другой метод, который должен вернуть задачу. Источник завершения устанавливает его результат как Task<IBitmap>
, а затем я возвращаю задачу CompletionSource, которая теперь становится Task<Task<IBitmap>>
Итак, что я получаю в качестве окончательного значения возврата Task<Task<IBitmap>>
вместо просто Task<Bitmap>
,
public Task<IBitmap> GetAlbumCoverImage(IAlbum album)
{
var assets = PHAsset.FetchAssetsUsingLocalIdentifiers(new string[] { album.Identifier }, null);
var asset = assets.FirstOrDefault(item => item is PHAsset);
if(asset == null)
{
return null;
}
var taskCompletionSource = new TaskCompletionSource<Task<IBitmap>>();
PHImageManager.DefaultManager.RequestImageForAsset(
asset,
new CoreGraphics.CGSize(512, 512),
PHImageContentMode.AspectFit,
null,
(image, info) => taskCompletionSource.SetResult(this.ConvertUIImageToBitmap(image)));
return taskCompletionSource.Task;
}
private Task<IBitmap> ConvertUIImageToBitmap(UIImage image)
{
var imageData = image.AsJPEG().GetBase64EncodedData(Foundation.NSDataBase64EncodingOptions.SixtyFourCharacterLineLength);
byte[] imageBytes = new byte[imageData.Count()];
System.Runtime.InteropServices.Marshal.Copy(imageData.Bytes, imageBytes, 0, Convert.ToInt32(imageData.Count()));
return BitmapLoader.Current.Load(new MemoryStream(imageBytes), 512, 512);
}
Как мне развернуть вложенную задачу, чтобы я только возвращал Task<IBitmap>
?
1 ответ
Вам не нужно использовать TaskCompletionSource<Task<IBitmap>>
использовать TaskCompletionSource<UIImage>
которая возвращает задачу, которая после завершения возвращает изображение. Ожидайте эту задачу, чтобы асинхронно получить результат, который затем можно преобразовать, используя ConvertUIImageToBitmap
:
public async Task<IBitmap> GetAlbumCoverImage(IAlbum album)
{
// ...
var taskCompletionSource = new TaskCompletionSource<UIImage>(); // create the completion source
PHImageManager.DefaultManager.RequestImageForAsset(
asset,
new CoreGraphics.CGSize(512, 512),
PHImageContentMode.AspectFit,
null,
(image, info) => taskCompletionSource.SetResult(image)); // set its result
UIImage image = await taskCompletionSource.Task; // asynchronously wait for the result
return await ConvertUIImageToBitmap(image); // convert it
}