Reputation: 5451
I want to convert the AWS S3 async methods into a Task using something like this:
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
);
}
However, I get the following exception:
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)
Is my call to FromAsync
incorrect or is something else going wrong here?
P.S.
Upvotes: 6
Views: 5225
Reputation: 1190
I am experiencing the same issue. Your FromAsync call is correct. The same issue exists when calling BeginPutObject/EndPutObject directly without the FromAsync wrapper.
The synchronous method AmazonS3Client.PutObject() has this body:
IAsyncResult asyncResult;
asyncResult = invokePutObject(request, null, null, true);
return EndPutObject(asyncResult);
Whereas AmazonS3Client.BeginPutObject says:
return invokePutObject(request, callback, state, false);
Note the last boolean parameter to invokePutObject. This argument is called 'synchronized'. If you call it with synchronized=true, it works (by performing the operation synchronously). If you call it with synchronized=false, under concurrent load, you get the exception you posted.
It's clearly a bug in the AWS SDK that needs further investigation. This post on the AWS forums looks similar, but it might not be the same issue; I'm unsatisfied with the upstream reply there, since concurrent synchronous uploads do work.
ETA: The new AWS SDK version 2.0 (in beta at the time of writing), which requires .Net 4.5, has native FooAsync methods (insted of Begin/EndFoo). It's based on the new System.Net.HttpClient library instead of the old HttpWebRequest. It almost certainly doesn't have this bug, but I haven't tested it yet myself.
Upvotes: 4