即使我锁定了我的列表,我的列表也不是线程安全的
本文关键字:我的 列表 线程 安全 锁定 | 更新日期: 2023-09-27 18:36:30
我得到:
"集合已修改枚举操作可能无法执行"在此 lline 中:
foreach (Message msg in queue)
过了一会儿。
我必须使用 .NET 2.0。
我在私有列表上所做的两个操作<>名为"队列"如下:
// 1st function calls this
lock (queue)
{
queue.Add(msg);
}
// 2nd function calls this
lock (queue)
{
using (StreamWriter outfile = new StreamWriter("path", true)
{
foreach (Message msg in queue) // This is were I get the exception after a while)
{
outfile.WriteLine(JsonConvert.SerializeObject(msg));
}
queue = new List<Message>();
}
}
我做错了什么?
(下面;好吧,我想不出会导致这种情况的竞争条件......但是:谁知道呢...
首先,你真的需要寻找一些与列表对话的其他代码;问题不在于你发布的代码。我怎么知道?因为在你枚举(
foreach (Message msg in queue)
)的时候,你有一个锁queue
,我们没有对锁对象的(非常狡猾,但不相关的)重新分配做任何事情。
对于此foreach
错误意味着其他内容正在更改列表。首先要做的,非常简单,是重命名列表字段。这将很快显示其他代码是否触及列表。还要检查您是否永远不会在此代码之外公开列表,即永远不会从任何地方return queue;
。
问题似乎不在您显示的代码中。重新分配锁定对象是一种不好的做法,你不应该这样做 - 但是:我看不到它实际上会破坏它的场景(显示的代码)。
列表不是这里的最佳模型,重新分配锁定对象不是一个好主意。要是有一个内置类型来表示队列就好了......
private readonly Queue<Message> queue = new Queue<Message>();
...
lock (queue) {
queue.Enqueue(msg);
}
// 2nd function calls this
lock (queue) {
if(queue.Count == 0) continue; // taken from comments
using (StreamWriter outfile = new StreamWriter("path", true) {
while(queue.Count != 0) {
Message msg = queue.Dequeue();
outfile.WriteLine(JsonConvert.SerializeObject(msg));
}
}
}
无需清除,因为Dequeue
本质上和有效地做到这一点。
lick 语句使用的参数应该是只读的。查看此链接
使用readonly private object
而不是queqe
代码应该是
eadonly object _object = new object();
// 1st function calls this
lock (_object)
{
queue.Add(msg);
}
// 2nd function calls this
lock (_object)
{
using (StreamWriter outfile = new StreamWriter("path", true)
{
foreach (Message msg in queue) // This is were I get the exception after a while)
{
outfile.WriteLine(JsonConvert.SerializeObject(msg));
}
queue = new List<Message>();
}
}