下面的代码示例会偶尔导致访问冲突(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
除了
中被阻止(没有例外或其他任何东西)的那个答案 0 :(得分:1)
异常System.AccessViolationException
只能来自非托管代码或不安全的托管代码。你上面的内容是普通的(即安全的)托管代码,所以你现在不应该仔细检查那些代码,而是关注其他可能性:
!analyze
命令会自动为您进行分析。您必须知道如何修复第3方库和第3方库的符号。示例是here。 如果您合理地排除了#1和#2,并且怀疑#3可能是问题,那么您应该收集崩溃转储并将其发送给Microsoft,只有他们能够在这种情况下提供帮助。