当需要线程安全集合(例如Set)时,现在的标准是什么.我自己同步它,还是有固有的线程安全集合?
我有一个通用列表如下
public static readonly List<Customer> Customers = new List<Customer>();
Run Code Online (Sandbox Code Playgroud)
我正在使用以下方法:
.Add
.Find
.FirstOrDefault
Run Code Online (Sandbox Code Playgroud)
最后2个是LINQ扩展.
我需要使这个线程安全的能够运行容器类的多个实例.
怎么实现呢?
我不太确定,所以我想我会问.删除和添加System.Collections.Generic.List<>对象的项是非线程安全的吗?
我的情况:
当收到连接时,它会被添加到列表中,但同时也会有一个正在删除死连接的工作人员等.
有问题吗?会lock吗?我也想知道我是否可以使用它的Foreach<>方法在列表对象上使用锁.
我非常熟悉,ReaderWriterLockSlim但我EnterUpgradeableReadLock()最近在一个类中尝试实现...不久之后我意识到当2个或更多线程运行代码时,这几乎肯定是一个保证死锁:
Thread A --> enter upgradeable read lock
Thread B --> enter upgradeable read lock
Thread A --> tries to enter write lock, blocks for B to leave read
Thread B --> tries to enter write lock, blocks for A to leave read
Thread A --> waiting for B to exit read lock
Thread B --> waiting for A to exit read lock
Run Code Online (Sandbox Code Playgroud)
我在这里错过了什么?
编辑
添加了我的场景的代码示例.该Run()方法将由两个或多个线程同时调用.
public class Deadlocker
{
private readonly ReaderWriterLockSlim _lock …Run Code Online (Sandbox Code Playgroud) 所以我在ConcurrentDictionary中有一个IList作为值.
ConcurrentDictionary<int, IList<string>> list1 = new ConcurrentDictionary<int, IList<string>>;
Run Code Online (Sandbox Code Playgroud)
为了更新列表中的值,我这样做:
if (list1.ContainsKey[key])
{
IList<string> templist;
list1.TryGetValue(key, out templist);
templist.Add("helloworld");
}
Run Code Online (Sandbox Code Playgroud)
但是,在templist中添加字符串是否会更新ConcurrentDictionary?如果是,那么更新是否是线程安全的,以便不会发生数据损坏?
或者是否有更好的方法来更新或创建ConcurrentDictionary中的列表
编辑
如果我使用ConcurrentBag而不是List,我将如何实现它?更具体地说,我该如何更新它?ConcurrentDictionary的TryUpdate方法感觉有点过分.
ConcurrentBag.Add是否在线程安全的mannar中更新ConcurrentDictionary?
ConcurrentDictionary<int, ConcurrentBag<string>> list1 = new ConcurrentDictionary<int, ConcurrentBag<string>>
Run Code Online (Sandbox Code Playgroud) 我正在研究一个简单的irc聊天机器人(专门用于twitch.tv流),我正在使用List来保存频道中所有用户的列表.当有人离开或加入时,我会从列表中添加或删除它们.然后我有一个每分钟运行的线程,检查流是否在线,如果是,它会向我的用户列表中的所有人分发"货币".
我相信你已经可以看到我的问题所在.如果有人在我的程序循环遍历列表中的用户时离开或加入,那么我会得到一个Collection Modified异常.目前,作为一种解决方法,我只是创建一个临时列表并将真实列表复制到其中,然后循环遍历临时列表,但我只是好奇是否有"更好"的方法来做到这一点?
快速伪代码:
private List<string> users = new List<string>();
private void IrcInitialize(){
//connect to irc stuff
//blah
//blah
//blah
Thread workThread = new Thread(new ThreadStart(doWork());
workThread.Start();
}
private void ircListener(){
parseIRCMessage(StreamReader.ReadLine());
}
private void parseIRCMessage(msg){
if (msgType == "JOIN"){
users.Add(user);
}
else if (msgType == "PART"){
users.Remove(user);
}
}
private void doWork(){
while (true) {
if (streamOnline() && handOutTime()){
handOutCurrency();
}
Thread.Sleep(60000);
}
}
private void handOutCurrency(){
List<string> temp = users; //This is what I'm currently doing
foreach (String …Run Code Online (Sandbox Code Playgroud) 新命名空间System.Collections.Concurrent包含字典,队列和堆栈以及其他类的并发集合.任何人都知道为什么没有ConcurrentList?
我发布了一个新问题,解释了我目前的情况.我更倾向于改变原始问题的整体意义.这是新问题的链接.
.net thread-safety task-parallel-library concurrent-collections
由于我的状态不一致,我似乎得到了线程错误IEnumerable.具体来说,List<T>.
这是我的工作流程:
List<string> IDs = getIDs();
RunTask(IDs);
RunTask(IDs);
public void RunTask(List<string> IDs)
{
TaskScheduler scheduler = new TaskScheduler();
TaskFactory factory = new TaskFactory(scheduler);
var tasks = IDs.Select(name => factory.StartNew(() => action(name))).ToArray();
Task.WaitAll(tasks);
}
Run Code Online (Sandbox Code Playgroud)
我的WaitAll()通话中出现了一般错误.
我的想法是我得到某种不同步的IEnumerator,我需要复制我的Listvia Array.CopyTo(),然后将它传递给我的多个线程.
这是我的例外:
Error: One or more errors occurred.
One or more errors occurred.
at System.Threading.Tasks.Task.WaitAll(Task[] tasks, Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.WaitAll(Task[] tasks, Int32 millisecondsTimeout)
at System.Threading.Tasks.Task.WaitAll(Task[] tasks)
Run Code Online (Sandbox Code Playgroud)
对此事有何想法?