在将值导出到列表 ex 的情况下以及在清除该字典之后使 ConcurrentDictionary 线程安全的任何想法。这样任何其他线程都无法在导出和清除之间添加数据。
像这样: ”
List<data> list;
list = (List<data>)_changedItems.Values; //get values before clearing
_changedItems.Clear();
Run Code Online (Sandbox Code Playgroud)
" 并且添加是由其他线程使用函数 _changedItems.AddOrUpdate 完成的
现在,如果某个线程在清除行之前将数据对象添加到集合中,则在从字典中获取数据和清除内容之间可能会丢失新数据。
或者是添加和清除内部锁的唯一方法。
lock(object)
{
List<data> list;
list = (List<data>)_changedItems.Values;
_changedItems.Clear();
}
Run Code Online (Sandbox Code Playgroud)
和
lock(object)
_changedItems.AddOrUpdate
Run Code Online (Sandbox Code Playgroud)
需要一个清除函数来安全地从字典中返回所有已清除的项目。
-拉里
c# multithreading dictionary thread-safety concurrentdictionary
我使用a ConcurrentDictioanry<string, HashSet<string>>来访问许多线程中的一些数据.
我在本文中读到(向下滚动)该方法AddOrUpdate未在锁中执行,因此可能危及线程安全.
我的代码如下:
//keys and bar are not the concern here
ConcurrentDictioanry<string, HashSet<string>> foo = new ...;
foreach(var key in keys) {
foo.AddOrUpdate(key, new HashSet<string> { bar }, (key, val) => {
val.Add(bar);
return val;
});
}
Run Code Online (Sandbox Code Playgroud)
为了确保一切都是线程安全的,我应该将声明括AddOrUpdate在lock声明中吗?
我是C#ConcurrentDictionary类的新手,我想知道如何GetOrAdd以异步方式在方法中使用valueFactory .
public class Class1
{
public int X = 10;
public Class1(int x)
{
X = x;
Debug.WriteLine("Class1 Created");
}
}
Run Code Online (Sandbox Code Playgroud)
在WinForm按钮中测试代码逻辑:
private async void button1_Click(object sender, EventArgs e)
{
var asyncDict = new ConcurrentDictionary<int, Task<Class1>>();
Func<int, Task<Class1>> valueFactoryAsync = async (k) => new Class1(await Task.Run(async () =>
{
await Task.Delay(2000);
Debug.WriteLine("Async Factory Called");
return 5;
}));
var temp = await(asyncDict.GetOrAdd(1, valueFactoryAsync)).ConfigureAwait(false);
Debug.WriteLine(temp.X);
temp.X = 20;
var temp2 = await (asyncDict.GetOrAdd(1, valueFactoryAsync)).ConfigureAwait(false);
Debug.WriteLine(temp2.X);
}
Run Code Online (Sandbox Code Playgroud)
当第二次调用GetOrAdd方法时,它从并发字典返回一个Task.然后我在任务上调用await, …
我最近遇到了一个问题,想解释一下原因:
在使用Profile5 (.Net 4, Windows 8)的便携式类库 (PCL) 中,我有以下代码:
using System.Collections.Concurrent;
public class Foo
{
public static void Bar(ConcurrentDictionary<string, bool> dict)
{
dict.AddOrUpdate("true", true, (k, v) => true);
}
public static void Baz()
{
new ConcurrentDictionary<string, bool>();
}
}
Run Code Online (Sandbox Code Playgroud)
Bar在 Windows 10 UWP 应用程序中使用,如下所示:
var dict = new ConcurrentDictionary<string, bool>();
Foo.Bar(dict);
Run Code Online (Sandbox Code Playgroud)
它编译但崩溃:
找不到方法:'Void Foo.Bar(System.Collections.Concurrent.ConcurrentDictionary`2)'。
对 Baz 的调用以不同的方式失败:
尝试通过方法 'Foo.Baz()' 访问方法 'System.Collections.Concurrent.ConcurrentDictionary`2..ctor()' 失败。
所以看起来TypeForwardedTo魔法在这种情况下不起作用,或者消失了。编译器理解它应该是相同的类型(即使存在于不同的程序集中)但运行时没有。
在运行时使用反射,我可以看到确实有ConcurrentDictionary两种类型:
System.Collections.Concurrent.ConcurrentDictionary'2[[TKey, TValue]], System.Collections.Concurrent, Version=4.0.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 当我使用 typeof(ConcurrentDictionary<,>)System.Collections.Concurrent.ConcurrentDictionary'2[[TKey, TValue]], …我有一个字典只支持add和modify操作并且可以并发操作,但总是针对不同的键。键是 int,值是引用类型。修改还意味着更改值的某些属性。
我的问题是:
谢谢!
ConcurrentDictionary.GetOrAdd(TKey,Func <TKey,TValue>)接受一个工厂函数,允许将项目的延迟实例化放入字典中.
定义一个自己调用GetOrAdd()的工厂函数是安全的,即在'父'GetOrAdd()的上下文中调用GetOrAdd.
以下代码演示了该模式; 它确实有效,但它安全吗?
class Program
{
static ConcurrentDictionary<string,object> __dict = new ConcurrentDictionary<string, object>();
static void Main(string[] args)
{
Foo foo = GetOrAddFoo();
Console.WriteLine(foo._name);
Console.WriteLine(foo._bar._name);
Console.ReadKey();
}
static Bar GetOrAddBar()
{
Console.WriteLine("GetOrAddBar: enter");
Func<string,Bar> factoryFn = (x) => LoadBar(x);
Bar bar = __dict.GetOrAdd("bar", factoryFn) as Bar;
Console.WriteLine("GetOrAddBar: exit");
return bar;
}
static Foo GetOrAddFoo()
{
Console.WriteLine("GetOrAddFoo: enter");
Func<string,Foo> factoryFn = (x) => LoadFoo(x);
Foo foo = __dict.GetOrAdd("foo", factoryFn) as Foo;
Console.WriteLine("GetOrAddFoo: exit");
return foo;
}
static Bar LoadBar(string …Run Code Online (Sandbox Code Playgroud) 在 .NET Framework 中,有Dictionary和ConcurrentDictionary. 这些提供诸如Add,Remove等方法...
我知道当我们设计一个多线程程序时,我们使用ConcurrentDictionary来代替Dictionary线程安全。
我不知道为什么ConcurrentDictionary有AddOrUpdate,GetOrAdd和类似的方法,同时Dictionary也没有。
我们总是喜欢下面的代码从 a 获取对象Dictionary:
var dict = new Dictionary<string, object>();
object tmp;
if (dict.ContainsKey("key"))
{
tmp = dict["key"];
}
else
{
dict["key"] = new object();
tmp = new object();
}
Run Code Online (Sandbox Code Playgroud)
但是在使用时ConcurrentDictionary,类似的代码只有一行。
var conDict = new ConcurrentDictionary<string, object>();
var tmp = conDict.GetOrAdd("key", new object());
Run Code Online (Sandbox Code Playgroud)
我希望 .NET 有这些方法,但为什么没有呢?
TL;DR: a 的单个枚举是否可以ConcurrentDictionary两次发出相同的键?该类的当前实现(.NET 5)是否ConcurrentDictionary允许这种可能性?
我有一个ConcurrentDictionary<string, decimal>由多个线程同时变异的 ,我想定期将其复制到普通Dictionary<string, decimal>,并将其传递到表示层以更新 UI 。有两种复制它的方法,带快照语义和不带快照语义:
var concurrent = new ConcurrentDictionary<string, decimal>();
var copy1 = new Dictionary<string, decimal>(concurrent.ToArray()); // Snapshot
var copy2 = new Dictionary<string, decimal>(concurrent); // On-the-go
Run Code Online (Sandbox Code Playgroud)
我非常确定第一种方法是安全的,因为该ToArray方法返回以下内容的一致视图ConcurrentDictionary:
返回一个新数组,其中包含从 复制的键和值对的快照
ConcurrentDictionary<TKey,TValue>。
但我更喜欢使用第二种方法,因为它产生的争用较少。我担心获得的可能性ArgumentException: An item with the same key has already been added.该文档似乎并没有排除这种可能性:
从字典返回的枚举器...并不代表字典的即时快照。通过枚举器暴露的内容可能包含
GetEnumerator调用后对字典所做的修改。
这是让我担心的情况:
ConcurrentDictionary,并且键X由枚举器发出。然后该线程被操作系统暂时挂起。有各种 帖子/答案表示,如果键尚不存在,则ConcurrentDictionary GetOrAdd当使用委托计算要插入字典中的值时,.NET/.NET Core 的方法不是线程安全的。Func
我相信,当使用 aConcurrentDictionary的方法的工厂方法时GetOrAdd,如果“同时”发生多个请求,则可以“同时/快速连续地”多次调用它。这可能会造成浪费,尤其是当呼叫“昂贵”时。(@panagiotis-kanavos 比我解释得更好)。有了这个假设,我正在努力理解我制作的一些示例代码似乎是如何工作的。
我已经在 .NET Fiddle 上创建了一个工作示例,但我一直试图理解它是如何工作的。
普通的推荐我读过的建议/想法是Lazy<Task<T>>在ConcurrentDictionary. 这个想法是阻止Lazy其他调用执行底层方法。
完成繁重工作的代码的主要部分是这样的:
public static async Task<DateTime> GetDateFromCache()
{
var result = await _cache.GetOrAdd("someDateTime", new Lazy<Task<DateTime>>(async () =>
{
// NOTE: i've made this method take 2 seconds to run, each time it's called.
var someData = await GetDataFromSomeExternalDependency();
return DateTime.UtcNow;
})).Value;
return result;
}
Run Code Online (Sandbox Code Playgroud)
我是这样读的:
是否有类似于ConcurrentDictionary<TKey,TValue>和的数据结构Interlocked.Exchange<T>(...),它允许您自动设置新值并检索分配给任意键的旧值?任何超载似乎都不可能AddOrUpdate(...)。