6

次のようなものを使用して、AWS S3 非同期メソッドをタスクに変換したいと考えています。

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間違っていますか、それともここで何か問題がありますか?

PS

  • .NET フレームワーク 4.5
  • AWSSDK バージョン 1.5.17.0
4

1 に答える 1

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 フォーラムのこの投稿は似ていますが、同じ問題ではない可能性があります。同時同期アップロードが機能するため、アップストリームの返信には満足していません。

ETA : .Net 4.5 を必要とする新しい AWS SDK バージョン 2.0 (執筆時点ではベータ版) には、ネイティブ FooAsync メソッド (Begin/EndFoo の代わり) があります。これは、古い HttpWebRequest ではなく、新しい System.Net.HttpClient ライブラリに基づいています。ほとんどの場合、このバグはありませんが、まだ自分でテストしていません。

于 2013-05-08T09:58:06.240 に答える