2

我的服务中有一个方法,该方法被我的视图模型调用以获取图像。该图像是从外部库(Xamarin中的iOS API)获取的,该库使用回调机制而不是等待。在TaskCompletionSource中展开异步操作和异步回调

为了让我的方法等待,我将该方法封装在TaskCompletionSource中。问题虽然在API回调中,但我需要调用另一个必须返回Task的方法。完成源将其结果设置为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>

回答

3

您不需要使用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 
} 
+0

这很好,谢谢。由于'ConvertUIImageToBitmap'需要一个UIImage,因此我必须将完成源更改为'TaskCompletionSource '。然后,我可以从等待的任务完成结果中提取UIImage,并将其传递到'ConvertUIImageToBitmap'方法并等待/返回结果。 –

+0

'ConvertUIImageToBitmap'确实需要返回一个任务。 'BitmapLoader.Current.Load'方法返回任务

+0

@JohnathonSullinger是的,我错过了'UIImage'部分,但这就是主意。 – i3arnon