并行Azure CloudBlockBlob操作崩溃(访问冲突)

时间:2015-01-29 13:22:25

标签: c# azure azure-storage azure-storage-blobs

下面的代码示例会偶尔导致访问冲突(5,000到10,000条消息中的1条)。使用序列foreach代替Parallel.ForEach似乎可以解决问题。

public void DequeBatch<T>(int count)
{
    var messages = this.queueListen.ReceiveBatch(count);
    var received = new ConcurrentBag<KeyValuePair<Guid, T>>();

    Action<BrokeredMessage> UnwrapMessage = message =>
        {
            blobName = message.GetBody<string>();
            obj = Download<T>(blobName);

            received.Add(new KeyValuePair<Guid, T>(new Guid(blobName), obj));
        };

    // offending operation
    Parallel.ForEach(messages, new ParallelOptions { MaxDegreeOfParallelism = count }, UnwrapMessage);
}

public override T Download<T>(string blobName)
{
    CloudBlockBlob blob;
    lock (this.containerDownloadLock)
    {
        blob = this.containerDownload.GetBlockBlobReference(blobName);
    }

    T result;
    using (var stream = new MemoryStream())
    {
        blob.DownloadToStream(stream);
        stream.Position = 0;
        result = Decompress<T>(stream);         // dehydrate an object of type T from a GZipStream
    }
    return result;
}

Q1 :使代码在线程不安全之上的违规部分是什么?

Q2 :并行下载CloudBlockBlob的正确和安全方法是什么?

修改

今天,上面列出的代码遇到了死锁。在调试器中遇到break-all后,我发现执行blob.DownloadToStream(stream);的所有工作线程都被困在

System.Net.AutoWebProxyScriptEngine.EnterLock

除了

中被阻止(没有例外或其他任何东西)的那个

System.Net.WinHttpProxyFinder.WinHttpGetProxyForUrl

1 个答案:

答案 0 :(得分:1)

异常System.AccessViolationException只能来自非托管代码或不安全的托管代码。你上面的内容是普通的(即安全的)托管代码,所以你现在不应该仔细检查那些代码,而是关注其他可能性:

  1. 您的应用中是否有任何非托管或不安全的代码?如果是这样,那可能是内存损坏的原因,这反过来会导致访问冲突。 Test your app under paged heap and GFlags
  2. 在调试器下执行您的应用并收集崩溃转储。查看故障转储并检查调用堆栈中是否有熟悉的代码。 Windgb的!analyze命令会自动为您进行分析。您必须知道如何修复第3方库和第3方库的符号。示例是here
  3. 这可能是微软实施Blob的一个错误。
  4. 如果您合理地排除了#1和#2,并且怀疑#3可能是问题,那么您应该收集崩溃转储并将其发送给Microsoft,只有他们能够在这种情况下提供帮助。