好吧,所以我遇到了一个奇怪的小问题,坦白说我没有想法.我想把它扔出去看看我是否遗漏了一些我做错了,或者ConcurrentDictionary无法正常工作的东西.这是代码:
(Cache是一个包含静态ConcurrentDictionary键的类)
var tmp = Cache.Keys.GetOrAdd(type,
key =>
{
var keys = context.GetKeys(key);
if (keys.Count() == 1)
{
return new KeyInfo
{
Name = keys.First().Name,
Info = key.GetInfo(keys.First().Name)
};
}
return null;
});
if (tmp == null)
Cache.Keys.TryRemove(type, out tmp);
return tmp;
Run Code Online (Sandbox Code Playgroud)
问题是,偶尔tmp会null导致TryRemove线路运行,但return null;上面的线路永远不会被击中.由于这return null是唯一将null进入词典,它永远不会运行,怎么可能tmp永远是null?
包括Cache类(此代码不使用SetNames):
public class Cache
{
public static ConcurrentDictionary<Type, Info> Keys = new ConcurrentDictionary<Type, Info>();
public static ConcurrentDictionary<Type, string> SetNames …Run Code Online (Sandbox Code Playgroud) 我有一个BlockingCollection(ConcurrentBag,50000),我试图为生产者线程使用一个非常小的有限容量50,000,以便最大化我可以在我的消费者线程的ConcurrentDictionary中处理的记录数.生产者比消费者快得多,并且会消耗大部分内存.
不幸的是,我立即注意到我的ConcurrentDictionary中的记录总数现在大大低于在我的测试数据执行时添加50,000的有界容量后的记录.我读到BlockingCollection的.add方法应该无限期地阻塞,直到集合中有空间来执行add.但是,情况似乎并非如此.
问题:
如果在BlockingCollection中的容量释放之前调用了太多的add,那么BlockingCollection的.add方法最终会超时或者无声地失败吗?
如果#1的答案是肯定的,那么在超过限制容量而不丢失数据后我可以尝试多少次添加?
如果调用了许多正在等待/阻塞容量的BlockingCollection .add()方法并且调用了CompleteAdding()方法,那些等待/阻塞添加会继续等待然后最终添加还是静默失败?
c# parallel-processing multithreading concurrentdictionary blockingcollection
.NET ConcurrentDictionary容易受到可能导致意外数据的竞争条件的影响,如本MSDN文章底部所述. 我假设有几个因素需要考虑.
问:我应该如何编写不易受可能导致数据丢失的竞争条件的代码?
在我的场景中,我有一个输入流,它具有一个始终增加的索引(n ++).我的想法是,如果竞争条件发生,我可以检测丢失的数据并重新发送.另一方面,可能有一种更好的方法可以做到这一点,我不知道.
c# multithreading .net-4.0 race-condition concurrentdictionary
如何使用Linq 创建Dictionary(甚至更好)a ConcurrentDictionary?
例如,如果我有以下XML
<students>
<student name="fred" address="home" avg="70" />
<student name="wilma" address="home, HM" avg="88" />
.
. (more <student> blocks)
.
</students>
Run Code Online (Sandbox Code Playgroud)
加载XDocument doc;并希望填充一个ConcurrentDictionary<string, Info>(其中键是名称,并且Info是一些持有地址和平均值的类.填充Info现在不是我的关注),我该怎么做?
如果我有一个ConcurrentDictionary并且想要使用该Add()函数,我需要转换为IDictionary:
var cd = new ConcurrentDictionary<int, int>();
cd.Add(1, 1); // Compile error: does not contain a definition for 'Add'
IDictionary<int, int> id = cd;
id.Add(1, 1); // Works
Run Code Online (Sandbox Code Playgroud)
问题ConcurrentDictionary和IDictionary告诉我这是因为使用私有方法显式ConcurrentDictionary实现IDictionary.
我的问题:为什么是ConcurrentDictionary这样实现的?隐藏使用已实现的接口有什么好处?
我正在使用并发字典来保存打开的文件。
要打开一个新文件,我这样做:
myDictionary.GetOrAdd (fName, (fn) => new StreamWriter(fn, true));
Run Code Online (Sandbox Code Playgroud)
因此,我经常收到以下异常:
System.IO.IOException: The process cannot access the file '....' because it is being used by another process.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPa
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
at System.IO.StreamWriter..ctor(String path, …Run Code Online (Sandbox Code Playgroud) 使用下面列出的普通字典代码,我得到了例外
集合被修改;枚举操作可能无法执行。
Dictionary<int, int> dict2 = new Dictionary<int, int>();
dict2.Add(1, 10);
dict2.Add(2, 20);
dict2.Add(3, 30);
dict2.Add(4, 40);
foreach (var d in dict2)
{
if (dict2.ContainsKey(2))
dict2.Remove(2);
if (dict2.ContainsKey(3))
dict2.Remove(3);
}
Run Code Online (Sandbox Code Playgroud)
但是对于 ConcurrentDictionary,这可以正常工作。
ConcurrentDictionary<int, int> dict1 = new ConcurrentDictionary<int, int>();
dict1.AddOrUpdate(1, 10, (k,v)=> 10);
dict1.AddOrUpdate(2, 20, (k, v) => 20);
dict1.AddOrUpdate(3, 30, (k,v)=> 30);
dict1.AddOrUpdate(4, 40, (k,v)=> 40);
foreach (var d in dict1)
{
int x;
if (dict1.ContainsKey(2))
dict1.TryRemove(2, out x);
if (dict1.ContainsKey(3))
dict1.TryRemove(3, out x);
}
Run Code Online (Sandbox Code Playgroud)
为什么会有行为差异?
我想用网络智慧澄清一些关于.net中多线程的时刻.互联网上有很多关于它的东西但是我无法找到我的问题的好答案.
假设我们希望在同类线程中保持安全状态.简单的情况是当state为int时:
class Class1
{
volatile int state = 0;
public int State
{
get
{
return state;
}
}
public Action<int> StateUpdated;
public void UpdateState(int newState)
{
state = newState;
if (StateUpdated != null)
StateUpdated(newState);
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,'volatile'应该足够了.无论什么线程需要获取当前状态,它都可以使用永远不会被缓存的"State"属性.无论线程想要更新状态,它都可以使用"UpdateState"安全地进行更新.
但是,如果州是一个结构,该怎么办?完全'锁定'是唯一的方法吗?附带问题:变量是否仍然可以缓存在锁内?
struct StateData
{
//some fields
}
class Class1
{
StateData state;
public StateData State
{
get
{
return state;
}
}
public Action<StateData> StateUpdated;
public void UpdateState(StateData newState)
{
state = newState;
if (StateUpdated != null)
StateUpdated(newState);
}
}
Run Code Online (Sandbox Code Playgroud)
最后的主要问题是:此代码是否足以在多线程环境中管理状态对象的集合?或者可能存在一些隐藏的问题. …
ConcurrentQueue有TryDequeue方法。
Queue就有Dequeue方法了。
没有ConcurrentDictionary方法Add,但我们有TryAdd。
我的问题是:
这些并发收集方法有什么区别?为什么它们对于并发集合不同?
我有一个像这样的 ConcurrentDictionary:
ConcurrentDictionary<int, Dto> concurrentDictionary = new ConcurrentDictionary<int, Dto>();
Run Code Online (Sandbox Code Playgroud)
这是一个可读可写的字典,可以被多个线程使用。我可以以线程安全的方式管理可写端。当我需要访问字典中的 Dto 时,我总是使用 Linq select 方法从中获取 Dto。
IEnumerable<Dto> dtos = concurrentDictionary.Select(p => p.Value);
Run Code Online (Sandbox Code Playgroud)
我知道,并发字典上的 Linq 方法对于可读和可写的并发字典来说是无锁和线程安全的。在我使用 Linq 访问 Dto 之后,在这些 Dto 上使用一些读取函数是否是线程安全的?我的意思是在 foreach 循环中访问这些 Dto 或从中创建新列表并对这些 Dto 的属性进行过滤或排序?
ConcurrentDictionary<int, Dto> concurrentDictionary = new ConcurrentDictionary<int, Dto>();
for (int i = 0; i < 10000; i++)
{
concurrentDictionary.TryAdd(i, new Dto()
{ Id = i, Name = RandomString(35), Type = "new", IsActive = true} );
}
IEnumerable<Dto> dtos = concurrentDictionary.Select(p => p.Value);
ArrayList arrayList …Run Code Online (Sandbox Code Playgroud) c# ×10
.net-4.0 ×2
concurrency ×2
dictionary ×2
linq ×2
.net ×1
collections ×1
enumeration ×1
volatile ×1