折腾 async/await 调用传统 Begin/End 异步方法

最近在改进园子的图片上传程序,希望实现用户上传图片时同时将图片文件保存在三个地方:1)服务器本地硬盘;2)又拍云;3)阿里云OSS。并且在保存时使用异步操作。

对于异步保存到本地硬盘,只需用 Steam.CopyToAsync() 将上传文件流异步复制到 FileStream 即可。

对于异步保存至又拍云,只要借助 WebRequest.GetRequestStreamAsync() + Steam.CopyToAsync() 就可以实现。

而阿里云OSS提供了 .NET SDK,使用起来很方便,但是之前并没有提供异步接口,成为异步化的一个障碍。

今天在 OSS .NET SDK 的更新日志中惊喜地发现:“添加异步化接口(支持Put/Get/List/Copy/PartCopy等异步操作)”。于是立马下载下来,可是一使用惊喜瞬间化为乌有 —— 新版 SDK 只提供了传统的 Begin/End 异步接口,却没有提供 async 异步接口。

public IAsyncResult BeginPutObject(string bucketName, string key, Stream content, AsyncCallback callback, object state);
public PutObjectResult EndPutObject(IAsyncResult asyncResult);

怀着失落的心情,望着孤零零的没有 await 陪伴的 async,心里有说不出的滋味。。。

async Task<bool> IBucket.PutFileAsync(string filePath, Stream uploadStream)
{
    filePath = filePath.Substring(1);
    uploadStream.Position = 0;
    _client.PutObject(_bucketName, filePath, uploadStream);
    return true;
}

难道这次只能实现半吊子的异步化吗?好不容易等来 OSS .NET SDK 支持异步化,难道只是空欢喜一场吗?真有些不甘心啊!

这时,心中突然闪过一个念头:有没有可能直接用 async/await 调用 Begin/End 异步方法?也许微软早就为我们准备好了馅饼?

于是,在网上搜寻了一番,发现了一线希望 —— 用 Task.Factory.FromAsync() 是可能实现的。

可是,一堆 FromAsync 方法看着就让人晕,只能一点点去试。

开始用的是 Task.Factory.FromAsync<PutObjectResult> ,但参数总对不上,比如:

await Task.Factory.FromAsync<PutObjectResult>(
                _client.BeginPutObject,
                _client.EndPutObject,
                _bucketName, filePath, uploadStream,
                null);

编译出错:

No overload for method ‘FromAsync‘ takes 6 arguments

后来改为下面这样,总算编译通过了:

await Task.Factory.FromAsync<PutObjectResult>(
                _client.BeginPutObject(_bucketName, filePath, uploadStream, null, null),
                x => { return _client.EndPutObject(x); });

而且运行程序,图片都能成功上传到阿里云OSS中,但总是报这样的错误:

failed: System.ArgumentException : retryableAsyncResult should not be null
	at Aliyun.OpenServices.OpenStorageService.Utilities.OssUtils.EndOperationHelper(IServiceClient serviceClient, IAsyncResult asyncResult)

这个错误说明 callback 调用没成功。

在这个地方折腾了很长时间,后来瞎猫碰着死耗子,把 Task.Factory.FromAsync<PutObjectResult> 改为 Task<PutObjectResult>.Factory.FromAsync 问题就解决了。代码如下:

async Task<bool> IBucket.PutFileAsync(string filePath, Stream uploadStream)
{
    filePath = filePath.Substring(1);
    uploadStream.Position = 0;
    var result = await Task<PutObjectResult>.Factory.FromAsync(
                    _client.BeginPutObject,
                    _client.EndPutObject,
                    _bucketName, filePath, uploadStream,
                    null);
    Console.WriteLine(result.ETag);
    return true;
}
时间: 2024-08-24 14:11:44

折腾 async/await 调用传统 Begin/End 异步方法的相关文章

异步编程之Async,Await和ConfigureAwait的关系

在.NET Framework 4.5中,async / await关键字已添加到该版本中,简化多线程操作,以使异步编程更易于使用.为了最大化利用资源而不挂起UI,你应该尽可能地尝试使用异步编程.虽然async / await让异步编程更简单,但是有一些你可能不知道的细节和注意的地方  新关键字 微软在.NET框架中添加了async和await关键字.但是,使用它们,方法的返回类型应为Task类型.(我们将在稍后讨论例外情况)为了使用await关键字,您必须在方法定义中使用async.如果你在方

C#学习日志 day8 -------------- async await 异步方法入门(引用博客)以及序列化和反序列化的XML及json实现

首先是异步方法的介绍,这里引用自http://www.cnblogs.com/LoveJenny/archive/2011/11/01/2230933.html async and await 简单的入门 如果有几个Uri,需要获取这些Uri的所有内容的长度之和,你会如何做? 很简单,使用WebClient一个一个的获取uri的内容长度,进行累加. 也就是说如果有5个Uri,请求的时间分别是:1s 2s 3s 4s 5s. 那么需要的时间是:1+2+3+4+5=(6*5)/2=15. 如果采用并

传统asp.net小心 async/await坑

最近在改老项目时,干了一件自以为很有成就感的事,心想 "项目都是同步方法,为啥不用异步方法呢?",于是有了异步方法,类型下面的代码(当然是举例子说明啊) //更新某人名下公司名称 public Task<bool> UpdateUser(string id,string companyName) { var usrInfo=Db.GetUsrInfo(id); var flag= await Db.UpdateCompanyNameAsync(usrInfo.company

Async Await异步调用WebApi

先铺垫一些基础知识 在 .net 4.5中出现了 Async Await关键字,配合之前版本的Task 来使得开发异步程序更为简单易控. 在使用它们之前 我们先关心下 为什么要使用它们.好比 一个人做几件事,那他得一件一件的做完,而如果添加几个人手一起帮着做 很显然任务会更快的做好.这就是并行的粗浅含义. 在程序中,常见的性能瓶颈在于 NetWork I/O 瓶颈 , CPU 瓶颈, 数据库I/O瓶颈,这些瓶颈使得我们的程序运行的很慢,我们想办法去优化.因为并行开发本身就加重CPU负担,所以一般

.net4.5的异步 async await 和Task

首先应该明白Task的概念-----任务 //这是一种优于Thread,甚至是ThreadPool的东西 而且是默认异步 再来理解async和await: 1.async只是配合await,用来声明异步方法的关键字: 2.async和await之间,await才是关键,直接含义——"异步等待",主线程运行至异步方法内的await处,一般情况下主线程会立即返回上层方法,而await处后续的任务(方法)会新开线程继续执行,新开线程在执行“等待”出任务(方法)结果后,会接着运行完异步方法内a

asyns和await实现传统的异步---------C#

传统的异步是利用回调函数来写的,写过的人都知道,,那样写的结构东一块西一块的,很不好找. 所以在这里整理啦一下asyns和await实现的异步... asyns和await的异步不是很好理解.在这里,我在注释中,将细细的标明 class Program { // ---------------规范说明----------------------------- //1.用async标识的方法即为异步方法,异步方法的返回值只能是void或者Task<object>,---返回值是void的方法,不

[.NET] 利用 async &amp; await 的异步编程

利用 async & await 的异步编程 [博主]反骨仔 [出处]http://www.cnblogs.com/liqingwen/p/5922573.html  目录 异步编程的简介 异步提高响应能力 更容易编写的异步方法 异步方法的控制流 线程 async 和 await 返回类型和参数信息 命名的约定 一.异步编程的简介 通过使用异步编程,你可以避免性能瓶颈并增强应用程序的总体响应能力. Visual Studio 2012 引入了一个简化的方法,异步编程,在 .NET Framewo

async/await使用深入详解

async和await作为异步模型代码编写的语法糖已经提供了一段时间不过一直没怎么用,由于最近需要在BeetleX webapi中集成对Task方法的支持,所以对async和await有了深入的了解和实践应用.在这总结一下async和await的使用,主要涉及到:自定义Awaitable,在传统异步方法中集成Task,异常处理等. 介绍 在传统异步方法处理都是通过指定回调函数的方式来进行处理,这样对于业务整非常不方便.毕竟业务信息和状态往往涉及到多个异步回调,这样业务实现和调试成本都非常高.为了

Javascript中的async await

async / await是ES7的重要特性之一,也是目前社区里公认的优秀异步解决方案.目前,async / await这个特性已经是stage 3的建议,可以看看TC39的进度,本篇文章将分享async / await是如何工作的,阅读本文前,希望你具备Promise.generator.yield等ES6的相关知识. 在详细介绍async / await之前,先回顾下目前在ES6中比较好的异步处理办法.下面的例子中数据请求用Node.js中的request模块,数据接口采用Github v3