使用.net async将对象放入Amazon S3

时间:2013-04-15 15:53:05

标签: c# amazon-s3 async-await

我想使用以下内容将AWS S3异步方法转换为Task:

using (var client = AWSClientFactory.CreateAmazonS3Client(accessKey, secretKey))
{
    var request = new PutObjectRequest();
    // ... set request properties ...

    await Task.Factory.FromAsync<PutObjectRequest, PutObjectResponse>(
        client.BeginPutObject,
        client.EndPutObject,
        request,
        null
    );
}

但是,我得到以下例外:

System.ArgumentException: The IAsyncResult object was not returned from the corresponding asynchronous method on this class.
Parameter name: asyncResult
   at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
   at Amazon.S3.AmazonS3Client.getResponseCallback[T](IAsyncResult result)
   at Amazon.S3.AmazonS3Client.endOperation[T](IAsyncResult result)
   at Amazon.S3.AmazonS3Client.EndPutObject(IAsyncResult asyncResult)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)

我对FromAsync的呼叫是否不正确,或者此处出现了其他问题?

P.S。

  • .NET Framework 4.5
  • AWSSDK版本1.5.17.0

1 个答案:

答案 0 :(得分:4)

我遇到了同样的问题。您的FromAsync呼叫是正确的。在没有FromAsync包装器的情况下直接调用BeginPutObject / EndPutObject时存在同样的问题。

同步方法AmazonS3Client.PutObject()有这个主体:

IAsyncResult asyncResult;
asyncResult = invokePutObject(request, null, null, true);
return EndPutObject(asyncResult);

而AmazonS3Client.BeginPutObject说:

return invokePutObject(request, callback, state, false);

注意invokePutObject的最后一个布尔参数。此参数称为“同步”。如果使用synchronized = true调用它,它可以工作(通过同步执行操作)。如果使用synchronized = false调用它,则在并发加载下,您将获得发布的异常。

这显然是AWS SDK中的一个需要进一步调查的错误。 AWS论坛上的This post看起来很相似,但可能不是同一个问题;我对那里的上游回复不满意,因为并发同步上传确实有效。

ETA :新的AWS SDK版本2.0(编写本文时为测试版),需要.Net 4.5,具有本机FooAsync方法(由Begin / EndFoo提供)。它基于新的System.Net.HttpClient库而不是旧的HttpWebRequest。它几乎肯定没有这个bug,但我还没有测试过它。