【发布时间】:2015-02-19 18:24:12
【问题描述】:
下面的代码示例有时会导致访问冲突(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:并行上传和下载CloudBlockBlobs 的正确且安全的方法是什么?
编辑
今天,上面列出的代码遇到了死锁。在调试器中点击 break-all 后,我观察到所有执行 blob.DownloadToStream(stream); 的工作线程都被困在了
System.Net.AutoWebProxyScriptEngine.EnterLock
除了一个在
中被阻止的(没有例外或其他任何东西)【问题讨论】:
-
异常时的调用堆栈是什么?
-
@S.T.不幸的是,大多数线程的调用堆栈根本没有显示任何代码。
-
它显示了什么?专门针对抛出异常的线程?
-
@S.T.确切的例外是未知模块中的
System.AccessViolationException。没有显示代码。
标签: c# azure azure-storage azure-blob-storage