Tag: 并发

ConcurrentDictionary似乎在删除时不标记GC的元素

我惊讶地发现我的应用程序内存占用不断增长 – 运行的时间越长,消耗的内存就越多。 因此,通过windbg一些魔力,我根据ConcurrentDictionary向我的小LRU缓存指出了一个问题。 CD有很多好处,对我来说非常酷(其中一个是它的数据永远不会在LOH中结束)。 TryRemove和TryRemove是用于添加和逐出项目的两种方法。 一些旧元素的!gcroot引导我回到我的缓存。 ILSpy的一些调查让我得出了这样的结论: TryRemove并没有真正删除元素。 它只是改变链表指针以跳过从不将数组元素的值赋值为null 。 这可以防止GC收集旧的被驱逐的对象。 真? 这是一个已知的问题吗? 如果是这样,我唯一的选择是TryUpdate(key, null) ,然后是TryRemove(key) ? 如果是这样,那么我必须锁定ConcurrentDictionary访问,这是矛盾的。 这是ILSpy转储: // System.Collections.Concurrent.ConcurrentDictionary private bool TryRemoveInternal(TKey key, out TValue value, bool matchValue, TValue oldValue) { while (true) { ConcurrentDictionary.Tables tables = this.m_tables; int num; int num2; this.GetBucketAndLockNo(this.m_comparer.GetHashCode(key), out num, out num2, tables.m_buckets.Length, tables.m_locks.Length); lock (tables.m_locks[num2]) { […]

将事务范围添加到Parallel.Foreach

我有一个循环将记录插入数据库(Firebird): using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, options)) { taskList.Add(Task.Factory.StartNew(() => { Parallel.ForEach(objectList, c => { DoInsert(c, id); }); })); scope.Complete() } 如果插入失败,我希望能够批量回滚这些插入。 但是,当我在Parallel.Foreach循环中执行插入时,事务范围不可见。 我假设那是因为循环在不同的线程中运行。 如果我使用TransactionScope作为串行插入执行此操作,一切正常。 我试图使用DependentTransaction但我似乎无法获取DoInsert函数的上下文。 DoInsert只是打开一个连接并将C的内容写入数据库。 有任何想法吗? 谢谢,

C#是否可以中断ThreadPool中的特定线程?

假设我在ThreadPool排队了一个工作项,但是如果没有要处理的数据,则工作项会阻塞(从BlockingQueue读取)。 如果队列为空并且没有更多的工作进入队列,那么如果我想中断阻塞任务,我必须调用Thread.Interrupt方法,但是如何使用ThreadPool做同样的事情? 代码可能如下所示: void Run() { try { while(true) { blockingQueue.Dequeue(); doSomething(); } } finally { countDownLatch.Signal(); } } 我知道在这种情况下最好的办法是使用常规的Thread ,但我想知道是否有一个ThreadPool等效方法来中断工作项。

在c#中,如何在multithreading环境中迭代IEnumerable

我在这种情况下,有一个大字典,由一个线程以相当高的频率随机更新,还有另一个线程试图将字典的快照保存为历史记录。 我目前正在使用这样的东西: Dictionary dict = new Dictionary(); var items = dict.Values.ToList(); 这在大多数情况下都可以正常工作,除非它偶尔抛出: System.InvalidOperationException:集合已被修改; 枚举操作可能无法执行。 我理解为什么会这样,但我不知道我该怎么做才能避免收集修改错误。 迭代此类集合的最佳方法是什么? 我也试过ConcurrentDictionary,但没有运气。 为什么? ConcurrentDictionary线程只在项目级别安全吗?

只读字典 – 多个线程调用.ContainsKey方法

我有一个静态只读字典。 不会对此词典进行任何修改。 我有多个线程使用.ContainsKey(Key)从这本字典中读取。 例如 class MyData { private static private IDictionary _dictionary = new Dictionary(); MyData() { // Load Dictionary here } public string GetValue(int key) { if (_dictionary.ContainsKey(key)) { return _dictionary[key]; } } } 这样做有任何线程问题吗?

C#并发,锁定和字典对象

我有一堆数据库实体加载到数据库对象中。 可以将相同的DB实体加载到多个DB对象中。 DB实体需要定期进行特殊处理。 此处理必须一次由一个线程执行。 在这里按顺序锁定。 编辑:重要说明:该过程调用慢速Web服务。 这就是我试图阻止并发的原因。 我不知道如何安全地完成没有锁。 所以我创建了一个“挂锁”对象,DB对象将引用该对象进行锁定。 挂锁对象是基于实体的,因此同一实体的两个或多个DB对象将使用相同的挂锁对象。 我使用数据库实体的ID作为密钥将这些挂锁存储在字典对象中。 挂锁对象也只是一个简单的字符串对象。 这是正确的方法吗? 我想我要么过度工程,要么简化这个。 如果方法是正确的,那么这段代码看起来如何? 它有效,但我还没有在负载下测试它。 谢谢 :) public static func(CustomObject o) { if (ReadyForUpdate(o)) { lock (LookupPadLockByID(object.ID) { if (ReadyForUpdate(o)) { PerformUpdate(object); } } } } private static readonly object padlockLock = new object(); private static readonly Dictionary padLocks = new Dictionary(); private static […]

并发下的队列为不同类型提供不同的结果

我刚刚开始了解一些新的.NET并发集合,如ConcurrentDictionary和ConcurrentQueue,我正在运行一些测试,看看当我与Queue并行编写时会发生什么。 所以我跑了这个: private static void ParallelWriteToQueue(Queue queue) { Stopwatch sw = Stopwatch.StartNew(); Parallel.For(1,1000001,(i) => queue.Enqueue(i)); sw.Stop(); Console.WriteLine(“Regular int Queue – ” + queue.Count + ” time” + sw.ElapsedMilliseconds); } 而且我认为我得到了下一个例外: Source array was not long enough. Check srcIndex and length, and the array’s lower bounds. 因此,此队列无法像预测的那样处理并发队列。 但是 ,当我将队列的类型更改为字符串时,没有exception,结果写了类似的东西 Regular string Queue – 663209 time117 这意味着只有大约663k被排队。 […]

同时访问MVC .NET上的数据

我有一个MVC网站,可以从数据库访问进程列表并选择一个“随机”进程,以便用户可以进行分析。 他可以批准或不批准该过程并自动接收另一个过程。 问题是几个用户将同时执行该过程,我需要阻止那些已经在审核的过程。 我不能在数据库方面这样做,所以必须是一个应用程序解决方案,对用户完全不可见…… 我该如何解决这个问题? —编辑 一种情况是:用户获取进程(进程被锁定),而不是“忘记”打开或“关闭”浏览器。 所以我需要以某种方式解锁这个过程。 我有一些想法: 使用MSMQ(当用户“忘记”完成任务时,是否可以放回进程?) 在我的webapp上使用静态ConcurrentBag来检查id列表。 (IIS回收会杀死该列表吗?) 谢谢

防止在Asp.net中使用ado.net并发执行SQL Server存储过程

我想阻止两个用户同时执行相同的存储过程。 如果两个asp.net请求进入执行该存储过程,那么这些请求应该以串行方式一个接一个地执行。 SQL Server数据库和执行由ado.net处理。 以下任何一种方法都有助于实现这一目标吗? 什么是最合适的方法? 有没有其他方法可以达到同样的目的? 通过将隔离级别设置为Serializable,使用ado.net事务执行存储过程 在存储过程中使用sp_getapplock并在最后释放

MSDN上的SimplePriorityQueue示例中存在严重错误

我需要使用并发优先级队列,我正在考虑在MSDN上调整如何:添加边界和阻塞function中给出的SimplePriorityQueue示例到一个收集教程。 但是,我对这个样本似乎有的错误的严重性感到惊讶。 有人可以validation这些问题是否确实存在? 1) TryAdd和ToArray之间存在竞争危险,这可能导致从后者抛出ArgumentException 。 TryAdd方法首先将项添加到内部队列,然后递增m_count计数器。 另一方面, ToArray首先初始化一个大小为m_count的新数组,然后将内部队列复制到该数组中。 如果在执行ToArray调用ToArray ,则ToArray可能最终会尝试复制比在数组中分配空间更多的项目,从而导致CopyTo调用抛出ArgumentException 。 private ConcurrentQueue<KeyValuePair>[] _queues; private int m_count; // … // IProducerConsumerCollection members public bool TryAdd(KeyValuePair item) { _queues[item.Key].Enqueue(item); Interlocked.Increment(ref m_count); return true; } public int Count { get { return m_count; } } public KeyValuePair[] ToArray() { KeyValuePair[] result; lock (_queues) { result = […]