C# 中的并发静态队列不保留我的数据
本文关键字:保留 我的 数据 队列 静态 并发 | 更新日期: 2023-09-27 18:32:20
所以我有一个在一个线程中处理并放入队列的数据,然后另一个线程正在删除信息并对其执行一些操作。
这是队列
public static class MyConcurrentQueue
{
public static ConcurrentQueue<cRule> _Queue;
public static void EnqueueRuleTrigger(cRule _Rule)
{
MyConcurrentQueue._Queue.Enqueue(_Rule);
}
}
在我有application_start
MyConcurrentQueue._Queue = new ConcurrentQueue<cRule>();
如果我想对我使用的规则进行排队
MyConcurrentQueue.EnqueueRuleTrigger(_Rule); //We're done enqueue the rule
取消排队我使用
MyConcurrentQueue._Queue.TryDequeue(out _Rule)
我注意到,如果将 2 个项目排队,一个接一个地在紧密循环中排队,到第一个取消排队 [单独的异步线程] 时,日志文件中的数据不再与排队匹配
如果我在排队之间设置睡眠,日志会读取正确的值,可能是因为一个项目被放入、取消排队,另一个项目被放入、取消排队。
我想这是因为队列是静态的,它存储的是_Rule的引用而不是它的副本。 关于如何解决此问题的任何想法? 我需要多个线程可以访问队列,这就是我首先将其设置为静态的原因。
提前谢谢。
编辑
这是我的排队和日志以及取消排队和日志逻辑
while (x<=y)
{
MyConcurrentQueue.EnqueueRuleTrigger(_Rule); //We're done enqueue the string AllText = File.ReadAllText(@"C:'Default'New.txt");
File.WriteAllText(@"C:'Default'New.txt", AllText + "'r'nEnqueue Alert:" +
_Rule.AlertID +":" + _Rule.TriggerStartTime + "-" + _Rule.TriggerEndTime);
}
这是在一个单独的线程上
if ( MyConcurrentQueue._Queue.TryDequeue(out _Rule))
{
... some logic
File.WriteAllText(@"C:'Default'New.txt", AllText + "'r'nDequeue Alert:" +
_Rule.AlertID + ":" + _Rule.TriggerStartTime + "-" + _Rule.TriggerEndTime);
}
这是我的日志文件
排队警报:64c88289-58a1-499b-ade9-3fa69a32cf47: 2012/4/27 12:00:00 PM-4/27/2012 5:00:00 PM
排队警报:64c88289-58a1-499b-ade9-3fa69a32cf47: 2012/4/28 14:00:00 PM-4/28/2012 21:00:00 PM
取消排队警报:64c88289-58a1-499b-ade9-3fa69a32cf47: 2012/4/28 14:00:00 PM-4/28/2012 21:00:00 PM
取消排队警报:64c88289-58a1-499b-ade9-3fa69a32cf47: 2012/4/28 14:00:00 PM-4/28/2012 21:00:00 PM
编辑:似乎是一个问题,与更改相同的对象并第二次排队相比。结果在取消排队期间,看起来第二个对象覆盖了第一个对象并插入了两次,实际上对同一对象的引用入了两次。
最有可能的解决方案是在插入之前进行深度克隆。请考虑使对象不可变,以简化代码的同步和可读性。
源语言:
最可能的原因是您的日志记录代码未正确同步。由于看起来您希望以原子方式发生 2 个操作(排队 + 日志或取消排队 + 日志),因此您必须在这两个操作周围添加适当的锁定,否则对队列和日志的调用顺序可能是半随机的。还要确保正确处理 TryDequeue 的结果(因为它可能返回 false)。
static object logAndQueueLock = new object();
public static void EnqueueRuleTrigger(Rule rule)
{
lock(logAndQueueLock)
{
MyConcurrentQueue._Queue.Enqueue(rule);
Log.Message("Enqueued:"+ rule.ToString());
}
}
public static Rule DequeueRuleTrigger()
{
lock(logAndQueueLock)
{
Rule rule = null;
if (MyConcurrentQueue._Queue.Enqueue(out rule)){
Log.Message("Enqueued:"+ rule.ToString());
}
return rule;
}
}