我试图通过为一些非常核心的函数引入缓存层来从我的数据库服务器卸载工作,这些函数将值插入数据库中的表并检索id.这是一个多线程环境.
我的第一个方法是:
public class Cache {
private Dictionary<string, Int64> i;
public void Init() { /* init i with values from DB */ }
public Int64 Get(string value)
lock(i) {
Int64 id;
if (cache.i.TryGetValue(value, out id))
return id;
id = /* Insert to DB and retrieve ID */
cache.i[value] = id;
return id;
}
}
Run Code Online (Sandbox Code Playgroud)
这有帮助.然而,线程仍然相互等待很多.我想减少这个等待时间.我的第一个想法是使用ConcurrentDictionary.GetOrAdd(key, valueFactory).这不起作用,因为可以多次调用valueFactory.
我已经结束了这种方法:
public class Cache
{
private ConcurrentDictionary<string, Int64> i;
public void Init() { /* init i with values from DB */ } …Run Code Online (Sandbox Code Playgroud) 我的场景是我想要一个ConcurrentDictionary像这样的方法.
bool TryRemove(TKey key, TValue value) {
// remove the value IF the value passed in == dictionary[key]
// return false if the key is not in the dictionary, or the value is not equal
}
Run Code Online (Sandbox Code Playgroud)
有没有办法同时做到这一点?我很难找到这个场景的答案,尽管看起来这是一个常见的用例.
我可以做这样的事情,但如果我已经使用了,我想避免锁定ConcurrentDictionary.我还必须锁定GetOrAdd()或AddOrUpdate()在其他地方打电话.似乎应该有一个更好的方法ConcurrentDictionary.
ConcurrentDictionary<int, string> dict = ...;
/// stuff
int keyTryToRemove = 1337;
string valTryToRemove = "someValue";
bool success = false;
lock(keyTryToRemove) {
string val;
if (dict.TryRemove(keyTryToRemove, out val)) {
if (val == valTryToRemove) …Run Code Online (Sandbox Code Playgroud) 最近,我需要在使用SortedDictionary和之间做出选择SortedList,并选择了SortedList.
但是,现在我发现我的 C# 程序在执行 SortedList.Count 时速度变慢了,我使用调用了数千次的函数/方法进行了检查。
通常我的程序会在 35 毫秒内调用该函数 10,000 次,但是在使用 时SortedList.Count,它减慢到 300-400 毫秒,基本上慢了 10 倍。
我也尝试过SortedList.Keys.Count,但这使我的性能又降低了 10 倍,超过 3000 毫秒。
I have only ~5000 keys/objects in SortedList<DateTime, object_name>. 我可以轻松、即时地从排序列表中检索数据SortedList[date] (in 35 ms),因此我没有发现列表结构或其持有的对象有任何问题。
这种表现正常吗?
我还能用什么来获取列表中的记录数,或者只是检查列表是否已填充?(除了添加一个单独的跟踪标志,我现在可以这样做)
更正:抱歉,我实际上正在使用:
ConcurrentDictionary<string, SortedList<DateTime, string>> dict_list = new ConcurrentDictionary<string, SortedList<DateTime, string>>();
我在不同的地方有不同的计数,有时检查列表中的项目,有时检查 ConcurrentDicitonary 中的项目。所以这个问题适用于 ConcurrentDicitonary,我编写了快速测试代码来确认这一点,这需要 350 毫秒,而不使用并发。这是 ConcurrentDicitonary 的测试,显示 350 毫秒:
public static void CountTest()
{
//Create test ConcurrentDictionary
ConcurrentDictionary<int, string> test_dict = …Run Code Online (Sandbox Code Playgroud) 以下哪两段代码在不同情况下表现更好,为什么?
1 .
private readonly ConcurrentDictionary<int, List<T>> _coll;
_coll.GetOrAdd(1, new List<T>());
Run Code Online (Sandbox Code Playgroud)
List即使不需要,这也会在每次调用时创建一个新的(如果我们通过capacity0?)。
2 .
private readonly ConcurrentDictionary<int, List<T>> _coll;
_coll.GetOrAdd(1, (val) => new List<T>());
Run Code Online (Sandbox Code Playgroud)
这仅创建List按需调用,但具有委托调用。
默认情况下,当通过多个线程访问时,非静态方法为每个线程都有自己的变量实例,因此如果它们不包含公共变量等,则会使它们成为线程安全的.
另一方面,静态方法中的变量在线程之间共享,默认情况下使它们非线程安全.
说,我有一个类,没有任何静态变量或方法.
public class Profile {
private ConcurrentDictionary<int, int> cache =
new ConcurrentDictionary<int, int>();
public AddToCache() {
}
public RemoveToCache() {
}
public DoSomethingThatShouldBeThreadSafe() {
}
}
Run Code Online (Sandbox Code Playgroud)
但后来我从这个类创建了一个静态对象.
public static Profile objProfile = new Profile();
Run Code Online (Sandbox Code Playgroud)
然后,使用多个线程访问objProfile.
问题是,Profile类,AddToCache,RemoveFromCache和DoSomethingThatShouldBeThreadSafe的方法是否在通过objProfile使用时是否是线程安全的?它们的变量是否会在线程之间共享,即使它们不是静态的,因为类的整个实例都是静态的?
我的问题很简单.经过大量谷歌搜索后,我了解到我可以在.NET 3.5项目中使用ConcurrentDictionary,使用其安装目录中的Reactive Extensions和System.Threading.dll版本.首先,没有System.Threading.dll,Reactive Extensions .NET 3.5子目录中只有System.Reactive.Windows.Threading.添加对System.Reactive或System.Reactive.Windows.Threading的引用或者从提到的.NET 3.5中的任何其他引用都没有给我ConcurrentDictionary类,也没有给我System.Collections.Concurrent命名空间.我已经下载了旧版本的Reactive Extensions SDK,我找到了我一直在寻找的东西,但我的问题是:有没有人知道Reactive Extensions的实际版本中ConcurrentDictionary backport发生了什么,有人知道它在哪里或为什么它是失踪.我根本无法找到合理的答案或任何答案.
ConcurrentDictionary我正在循环中填充 a Parallel.ForEach:
var result = new ConcurrentDictionary<int, ItemCollection>();
Parallel.ForEach(allRoutes, route =>
{
// Some heavy operations
lock(result)
{
if (!result.ContainsKey(someKey))
{
result[someKey] = new ItemCollection();
}
result[someKey].Add(newItem);
}
}
Run Code Online (Sandbox Code Playgroud)
如何在不使用 lock 语句的情况下以线程安全的方式执行最后的步骤?
编辑: 假设这ItemCollection是线程安全的。
c# parallel-processing task-parallel-library concurrentdictionary parallel.foreach
如何实现ToLookup()并发?我有一些这样的代码:
myRepository.GetAllContacts().ToLookup( c => c.COMPANY_ID);
Run Code Online (Sandbox Code Playgroud)
我想要一个与此类似的结构:
new ConcurrentDicitonary<String,IEnumerable<Contact>>(); // <Company,List of Contacts in company>
Run Code Online (Sandbox Code Playgroud)
因为每个都COMPANY_ID可以映射到多个Contact,所以我不能简单地使用ToDictionary.
如果我有一个ConcurrentDictionary对象,当在外部执行操作时,ConcurrentDictionary<int, Dictionary<string, string>>() dict;嵌套是否被锁定?DictionaryConcurrentDictionary
场景:外部人员ConcurrentDictionary outerDict正在执行
outerDict.Add(42, new Dictionary<string, string>())
在一个线程上,并且在另一个线程上(同时),内部Dictionary正在执行
outerDict[30].Add("hello", "world")。
上述场景中外层ConcurrentDictionary和内层的修改是否都是并发Dictionary,还是同时进行?
我有以下测试:
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program
{
public static void Main()
{
IDictionary<string, string> dictionary = new ConcurrentDictionary<string, string>(); // FAILS sometimes
// ConcurrentDictionary<string, string> dictionary = new ConcurrentDictionary<string, string>(); // WORKS always
Parallel.For(0, 10, i => dictionary.TryAdd("x1", "y1"));
}
}
Run Code Online (Sandbox Code Playgroud)
如果我在 .NET Fiddle 中运行它,有时会出现以下异常:
未处理的异常。System.AggregateException:发生一个或多个错误。(该键已存在于字典中)
System.ArgumentException:该键已存在于字典中。在 System.Collections.Concurrent.ConcurrentDictionary`2.System.Collections.Generic.IDictionary<TKey,TValue>.Add(TKey key, TValue value)
在 System.Collections.Generic.CollectionExtensions.TryAdd[TKey,TValue](IDictionary` 2 字典,TKey 键,TValue 值)
在 Program.<>c__DisplayClass0_0.b__0(Int32 i)
在 System.Threading.Tasks.Parallel.<>c__DisplayClass19_0`2.b__1(RangeWorker& currentWorker, Int64 timeout, Boolean&replicationDelegateYieldedBeforeCompletion)
---之前位置的堆栈跟踪结束 ---
在 System.Threading.Tasks.Parallel.<>c__DisplayClass19_0`2.b__1(RangeWorker& currentWorker, Int64 timeout, Boolean&replicationDelegateYieldedBeforeCompletion)
在 …