C# 展开异步操作并执行它';TaskCompletionSource中的异步回调

C# 展开异步操作并执行它';TaskCompletionSource中的异步回调,c#,xamarin.ios,async-await,task-parallel-library,taskcompletionsource,C#,Xamarin.ios,Async Await,Task Parallel Library,Taskcompletionsource,我的视图模型调用了一个服务中的方法来获取图像。图像是从外部库(Xamarin中的IOSAPI)获取的,该库使用回调机制而不是等待 为了使我的方法可以等待,我将该方法包装在TaskCompletionSource中。问题是在API回调中,我需要调用另一个必须返回任务的方法。completion source将其结果设置为一个任务,然后我返回CompletionSource任务,该任务现在变成任务,因此我最终的返回值是任务,而不仅仅是任务 公共任务GetAlbumCoverImage(IAlbum相

我的视图模型调用了一个服务中的方法来获取图像。图像是从外部库(Xamarin中的IOSAPI)获取的,该库使用回调机制而不是等待

为了使我的方法可以等待,我将该方法包装在TaskCompletionSource中。问题是在API回调中,我需要调用另一个必须返回任务的方法。completion source将其结果设置为一个
任务
,然后我返回CompletionSource任务,该任务现在变成
任务
,因此我最终的返回值是
任务
,而不仅仅是
任务

公共任务GetAlbumCoverImage(IAlbum相册) { var assets=PHAsset.fetchassetsunglocalidentifiers(新字符串[]{album.Identifier},null); var资产=资产。FirstOrDefault(项目=>项目已设置); 如果(资产==null) { 返回null; } var taskCompletionSource=新的taskCompletionSource(); PHImageManager.DefaultManager.RequestImageForAsset( 资产, 新的CoreGraphics.CGSize(512,512), PHImageContentMode.AspectFit, 无效的 (image,info)=>taskCompletionSource.SetResult(this.ConvertUIImageToBitmap(image)); 返回taskCompletionSource.Task; } 专用任务ConvertUIImageToBitmap(UIImage图像) { var imageData=image.AsJPEG().GetBase64EncodedData(Foundation.NSDataBase64EncodingOptions.SixtyFourCharacterLineLength); byte[]imageBytes=新字节[imageData.Count()]; System.Runtime.InteropServices.Marshal.Copy(imageData.Bytes,imageBytes,0,Convert.ToInt32(imageData.Count()); 返回BitmapLoader.Current.Load(新的MemoryStream(imageBytes),512); }
我应该如何展开嵌套的任务,以便只返回一个
任务

您不需要使用
TaskCompletionSource
,使用
TaskCompletionSource
,它返回一个任务,完成后返回一个图像。等待该任务异步获取结果,然后使用
convertuimagetobitmap
转换该结果:

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
}
公共异步任务GetAlbumCoverImage(IAlbum相册) { // ... var taskCompletionSource=new taskCompletionSource();//创建完成源 PHImageManager.DefaultManager.RequestImageForAsset( 资产, 新的CoreGraphics.CGSize(512,512), PHImageContentMode.AspectFit, 无效的 (image,info)=>taskCompletionSource.SetResult(image));//设置其结果 UIImage image=wait taskCompletionSource.Task;//异步等待结果 return wait wait convertuImageToBitmap(image);//转换它 }
这很有效,谢谢。由于
convertuimagetobitmap
需要一个UIImage,因此我不得不将完成源更改为
TaskCompletionSource
。然后,我可以从等待的任务完成结果中提取UIImage,并将其传递到
ConvertUIImageToBitmap
方法中,然后等待/返回结果。
ConvertUIImageToBitmap
实际上需要返回任务。
BitmapLoader.Current.Load方法返回Task@JohnathonSullinger是的,我错过了
UIImage
部分,但这就是我的想法。@JohnathonSullinger,这太令人惊讶了。您应该向任务返回方法(即
LoadAsync
)添加“Async”后缀。在这种情况下,我不控制API。加载方法是提供跨平台映像加载的OSS项目(Splat)。我将对API进行调整,以添加异步。我曾经在MSDN上读到,除非混合使用异步/同步方法,否则附加异步只是多余的。我想这只是个人喜好
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
}