我有以下内容ConcurrentDictionary:
ConcurrentDictionary<Guid, Session> sessions;
Run Code Online (Sandbox Code Playgroud)
我知道这sessions.TryGetValue(key, out session)是线程安全的,但我的问题是,它sessions[key]是否也是线程安全的?
sessions.TryGetValue(key, out session) 返回true或false,具体取决于它是否能够获取值.
如果无法获得价值,会sessions[key]返回null吗?我想是的.任何人都可以确认或更多地阐明这一点吗?谢谢.
我遇到了一个有趣的问题.知道ConcurrentDictionary<TKey, TValue>在被修改时安全可枚举,(在我的情况下)迭代可能消失或多次出现的元素的不必要的副作用,我决定自己创建一个快照,使用ToList().既然ConcurrentDictionary<TKey, TValue>也实现了ICollection<KeyValuePair<TKey, TValue>>,这会导致List(IEnumerable<T> collection)使用它Count,然后使用当前项目在字典的当前大小中创建一个数组,然后尝试复制项目using ICollection<T>.CopyTo(T[] array, int arrayIndex),调用它的ConcurrentDictionary<TKey, TValue>实现,最后抛出一个ArgumentExceptionif元素被添加在此期间到字典.
全部锁定会破坏使用集合的重点,所以我的选择似乎是继续捕获异常并重试(这绝对不是问题的正确答案),或者实现我自己的ToList()专用版本对于这个问题(但是再一次,简单地增加一个列表然后可能将其修剪为适合几个元素的大小似乎是一种过度杀伤,并且使用LinkedList会降低索引性能).
此外,似乎添加某些LINQ方法在后台创建某种缓冲区(例如OrderBy)似乎以性能为代价来修复问题,但裸露ToList()显然没有,并且它不值得"扩充"当不需要其他功能时,使用另一种方法.
这可能是任何并发收集的问题吗?
在创建此类快照时,将性能命中率降至最低的合理解决方法是什么?(最好在一些LINQ魔法结束时.)
编辑:
在调查之后,我可以确认,ToArray()(我认为我昨天刚刚通过它)确实解决了快照问题,只要它只是一个简单的快照,在拍摄快照之前需要额外的功能时它没有帮助(例如过滤,排序),最后还需要一个列表/数组.(在这种情况下,需要额外调用,重新创建新集合.)
我没有指出快照可能需要也可能不需要经过这些修改,所以应该在最后进行,最好是,所以我将这个添加到问题中.
(另外,如果有人对标题有更好的想法,请告诉.)
我有一个高效的C#应用程序,它在多线程CPU上以每秒5k到10k记录的速率接收80字节的数据.
我现在需要设置一个内存缓存来检测和过滤重复记录,这样我就可以抑制它们在管道中进一步移动.
缓存规格(最大阈值)
题
设置内存缓存,字典,哈希表,数组等的最佳方法是什么,它将允许最有效的查找,清除旧的缓存数据,并防止被击中的数据到期.
我查看了ASP.Net Cache,System.Runtime.MemoryCache,但我认为我需要一些更轻量级的东西来定制以获得正确的吞吐量.我也在看System.Collections.Concurrent作为替代和相关的白皮书.
有没有人对最佳方法有什么建议?
我有一个场景,我必须保持引用计数对象的给定键ConcurrentDictionary,如果引用计数达到0,我想删除键.这必须是线程安全的,因此我打算使用ConcurrentDictionary.
示例程序如下.在并发字典中,我有键和值,值是KeyValuePair,它保存我的自定义对象和引用计数.
ConcurrentDictionary<string, KeyValuePair<object, int>> ccd =
new ConcurrentDictionary<string, KeyValuePair<object, int>>();
// following code adds the key, if not exists with reference
// count for my custom object to 1
// if the key already exists it increments the reference count
var addOrUpdateValue = ccd.AddOrUpdate("mykey",
new KeyValuePair<object, int>(new object(), 1),
(k, pair) => new KeyValuePair<object, int>(pair.Key, pair.Value + 1));
Run Code Online (Sandbox Code Playgroud)
现在我想要一种方法来在引用计数达到0时删除密钥.我在想,删除带有ConcurrentDictionary键和谓词的方法,如果谓词返回'true'则删除密钥.例.
ConcurrentDictionary.remove(TKey, Predicate<TValue> ).
Run Code Online (Sandbox Code Playgroud)
没有这样的方法ConcurrentDictionary,问题是如何以线程安全的方式做同样的事情?
.net c# multithreading task-parallel-library concurrentdictionary
我有几种ConcurrentDictionary<TKey, TValue>用于缓存值的情况,但是我经常需要执行值的验证以决定是否使用它来将其添加到缓存中ConcurrentDictionary<TKey, TValue>.GetOrAdd(TKey, Func<TKey, TValue>).
通常沿着以下方向:
private readonly ConcurrentDictionary<Type, ISomeObject> someObjectCache =
new ConcurrentDictionary<Type, ISomeObject>();
public ISomeObject CreateSomeObject(Type someType)
{
return someObjectCache.GetOrAdd(someType, type =>
{
if(!Attribute.IsDefined(someType, typeof(SomeAttribute))
// Do something here to avoid the instance from being added to
// `someObjectCache`
ISomeObject someObject;
// Typical factory functionality goes here
return someObject;
});
}
Run Code Online (Sandbox Code Playgroud)
我今天这个处理的方式是抛出这似乎做工精细异常,但我想一个更简洁的方法(可能是一个标志,我可以设置或一个特定的值,我可以设置返回值)来取消GetOrAdd从内lambda(虽然它可以实际上被完整的方法取代).
基于我对其他类似LINQ的方法的经验,返回null将导致值被添加而不被检查(并且读取IL GetOrAdd看起来它会导致同样的问题),所以我不认为'工作.
有什么方法可以避免使用异常取消添加使用GetOrAdd?
我目前正在编写一个C#应用程序.我是使用ConcurrentDictionary的新手,因此对其线程安全性有一些疑问.首先,这是我的字典:
/// <summary>
/// A dictionary of all the tasks scheduled
/// </summary>
private ConcurrentDictionary<string, ITask> tasks;
Run Code Online (Sandbox Code Playgroud)
我在我的类中实例化它并使用它来跟踪实现ITask的所有对象.我想确保我的设置在多线程环境中正常工作.
如果多个线程想要获取ConcurrentDictionary中项目数的计数,我是否需要锁定它?
如果我想从字典中获取特定键,获取该键的对象并在其上调用方法,是否需要锁定它?例如:
/// <summary>
/// Runs a specific task.
/// </summary>
/// <param name="name">Task name.</param>
public void Run(string name)
{
lock (this.syncObject)
{
var task = this.tasks[name] as ITask;
if (task != null)
{
task.Execute();
}
}
}
Run Code Online (Sandbox Code Playgroud)
保持多个线程可以调用Run方法来调用ITask的Execute方法.我的目标是让一切线程安全且尽可能高效.
c# asp.net multithreading thread-safety concurrentdictionary
首先,使用索引分配(例如myConcurrentDictionary[someKey] = someValue;)将项目简单地添加到并发字典是否安全?
我只是感到困惑,因为它隐藏了IDictionary方法(例如Add).
为什么AddOrUpdate()需要func来更新值?是否有一种方法来设置密钥的值,无论密钥是否已存在?
我无法从MSDN页面收集到这些信息.
当我调用ConcurrentDictionary.ToArray时,有时我会收到以下错误.错误如下:
System.ArgumentException:索引等于或大于数组的长度,或者字典中的元素数大于从索引到目标数组末尾的可用空间.at System.Collections.Concurrent.ConcurrentDictionary
2.System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.CopyTo(KeyValuePair2 [] array,Int32 index)at System.Linq.Buffer1..ctor(IEnumerable1 source)at System.Linq.Enumerable.ToArray [TSource](IEnumerable1 source) at ...Cache.SlidingCache2.RemoveExcessAsync(Object state)in ...\SlidingCache.cs:System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext,ContextCallback callback,Object state,Boolean preserveSyncCtx)的第141行,位于System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback callback,Object state,Boolean preserveSyncCtx) System.Threading.ThreadPoolWorkQueue.Dispatch()中的.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
我注意到在多线程场景中,有时在对ConcurrentDictionary进行排序时会出现异常.见堆栈溢出的问题在这里.所以我在排序之前开始使用ConcurrentDictionary.ToArray.在创建阵列时似乎仍然存在问题.
并发字典用于缓存,当达到缓存的设置的最大元素数时,该缓存维护对象并刷新最后访问的对象.多个线程访问缓存,并且在尝试删除旧元素时发生上述错误,因此可以将新元素添加到数组中.请参阅下面的一些代码段:
public class SlidingCache<TKey, TValue> : IDictionary<TKey, TValue>
{
public int MinCount { get; private set; }
public int MaxCount { get; private set; }
private readonly IDictionary<TKey, CacheValue> _cache = new ConcurrentDictionary<TKey, CacheValue>();
public SlidingCache(int minCount=75000, int maxCount=100000)
{
if (minCount <= 2)
throw new ArgumentException("minCount"); …Run Code Online (Sandbox Code Playgroud) System.Collections.Concurrent.ConcurrentDictionary的MSDN文档说:
线程安全
所有公共成员和受保护成员
ConcurrentDictionary<TKey,?TValue>都是线程安全的,可以从多个线程同时使用.然而,构件通过接口中的一个访问的ConcurrentDictionary<TKey,?TValue>器具,包括扩展方法,不保证线程安全,并且可能需要由呼叫者进行同步.
(强调我的)
这似乎是自相矛盾的."所有成员都是线程安全的.但成员[有时]不是线程安全的."
我确实理解扩展方法当然不能保证是线程安全的.
但是"通过其中一个接口访问"是什么意思呢?是TryGetValue(IDictionary<TKey, TValue>接口的成员)线程安全吗?
我已经看到如何将ConcurrentDictionary转换为Dictionary,但我有一个字典,并希望转换为ConcurrentDictionary.我该怎么做?...更好的是,我可以将link语句设置为ConcurrentDictionary吗?
var customers = _customerRepo.Query().Select().ToDictionary(x => x.id, x => x);
Run Code Online (Sandbox Code Playgroud) c# ×8
.net ×5
asp.net ×2
c#-4.0 ×1
caching ×1
concurrency ×1
dictionary ×1
hashtable ×1
linq ×1
memorycache ×1
tolist ×1