混淆了EndUploadFromStream

时间:2012-09-28 07:58:30

标签: azure-storage azure-storage-blobs blobstorage

我对异步上传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文件上传到Azure blob,文件数量可能是10-50,000,每个文件大约是10KB-50KB。目前代码片段对我来说很好。但是,如果我在回调中调用EndUploadFromStream,它在上传超过2,000个文件时总是抛出异常。我的意思是如果我在upload方法中删除EndUploadFromStream并在回调(OnUploadCompleted方法)中调用EndUploadFromStream,则会发生异常。如下的异常消息:

无法从传输连接读取数据:连接已关闭.StackTrace:at Microsoft.WindowsAzure.StorageClient.Tasks.Task`1.get_Result()

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

我不知道为什么会这样......希望得到你们的回答。

感谢。

1 个答案:

答案 0 :(得分:0)

开始/结束代码看起来没问题。我注意到你没有做任何事情等待异步操作完成,所以问题可能与此有关。例如,如果您从控制台应用程序运行此应用程序,则应用程序可能会在所有上载完成之前退出,然后向您提供这些错误。如果EndUploadFromStream()调用位于Parallel.ForEach()内,则不会出现问题,因为它会导致Parallel.ForEach()调用阻塞,直到所有上传完成为止。

因此,尝试添加代码以等待所有上传完成,看看是否可以修复它。一种简单的方法是将计数器初始化为上载总数,然后在回调内递减(使用Interlocked.Decremement()进行线程安全)。另一个选项是使用Task.FromAsync()来获取Task对象数组,然后使用Task.WaitAll()等待它们完成。

另外,同时使用Parallel.ForEach()和Begin / End方法通常是多余的 - Begin / End已经是异步的,因此使用多个线程调用它通常没有意义。由于你有这么大的项目清单,可能在这种情况下会有所不同,但可能并不多。除非您实际测量到显着差异,否则您最好使用简单的foreach循环代替Parallel.ForEach()