0

非同期でblobをアップロードすることに関する問題と混同しています。ここで、答えが見つかることを願っています。

最初に私のコードスニペットを見てください、

public void UploadMultipleBlobs(List<string> filelocations, string containerName, AsyncCallback callback = null, string path = null)
    {
                    try
        {

            Parallel.ForEach(filelocations, fileLocation =>
                {

                    //File to Stream
                    MemoryStream str = new MemoryStream();
                    byte[] file = File.ReadAllBytes(fileLocation);
                    str.Write(file, 0, file.Length);
                    str.Seek(0, SeekOrigin.Begin);

                    //Operations
                    if (callback == null)
                        callback = new AsyncCallback(OnUploadCompleted);
                    BlobRequestOptions blobRequestOptions = new BlobRequestOptions();
                    blobRequestOptions.Timeout = new TimeSpan(1, 0, 0);
                    blobRequestOptions.RetryPolicy = retry;

                    CloudBlob currentBlob = container.GetBlobReference(blobName);
                    var result = currentBlob.BeginUploadFromStream(str, blobRequestOptions, callback, new Object[] { currentBlob, str });

                    currentBlob.EndUploadFromStream(result);
                });

        }
        catch
        {
            throw;
        }

    }

private void OnUploadCompleted(IAsyncResult result)
    {
        try
        {
            // Get array passed to callback
            Object[] states = (Object[])result.AsyncState;

            var blob = (CloudBlob)states[0];
            var stream = (MemoryStream)states[1];

            // End the operation
            //blob.EndUploadFromStream(result);

            // Close the stream
            stream.Close();
        }
        catch
        {
            throw;
        }
    }

mutilファイルをAzureBLOBにアップロードする必要があります。ファイルの数は10〜50,000で、各ファイルは約10KB〜50KBです。現在、コードスニペットは正常に機能しています。ただし、コールバックでEndUploadFromStreamを呼び出すと、2,000を超えるファイルをアップロードするときに常に例外がスローされます。つまり、uploadメソッドでEndUploadFromStreamを削除し、callback(OnUploadCompletedメソッド)でEndUploadFromStreamを呼び出すと、例外が発生します。以下のような例外メッセージ:

トランスポート接続からデータを読み取れません:接続が閉じられました。、StackTrace:Microsoft.WindowsAzure.StorageClient.Tasks.Task`1.get_Result()で

Microsoft.WindowsAzure.StorageClient.CloudBlob.EndUploadFromStream(IAsyncResult asyncResult)で

なぜそれが起こるのかわかりません...皆さんからの回答を期待しています。

ありがとう。

4

1 に答える 1

0

Begin/End コードは問題ないようです。非同期操作が完了するのを待つために何もしていないことに気付いたので、問題はそれに関連している可能性があります。たとえば、これをコンソール アプリケーションから実行している場合、すべてのアップロードが完了する前にアプリケーションが終了し、これらのエラーが発生することがあります。すべてのアップロードが完了するまで呼び出しがブロックされるため、EndUploadFromStream()呼び出しが 内にある場合は問題になりません。Parallel.ForEach()Parallel.ForEach()

そのため、すべてのアップロードが完了するのを待つコードを追加して、問題が解決するかどうかを確認してください。簡単な方法は、アップロードの総数に初期化されInterlocked.Decremement()、コールバック内で (スレッド セーフを使用して) デクリメントされるカウンターです。もう 1 つのオプションはTask.FromAsync()、Task オブジェクトの配列を取得するために使用Task.WaitAll()され、それらが完了するまで待機するために使用されます。

余談ですが、Parallel.ForEach()と Begin/End メソッドの両方を同時に使用するのは通常冗長です。Begin/End はすでに非同期であるため、通常、複数のスレッドを使用して呼び出しても意味がありません。アイテムのリストが非常に大きいため、この場合は多少の違いが生じる可能性がありますが、おそらくそれほど大きくはありません. 実際に有意な差を測定していない限り、単純なforeachループを使用する方がよいでしょう。Parallel.ForEach()

于 2012-09-28T16:33:08.223 に答える