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

C# 中的并发静态队列不保留我的数据

编辑:似乎是一个问题,与更改相同的对象并第二次排队相比。结果在取消排队期间,看起来第二个对象覆盖了第一个对象并插入了两次,实际上对同一对象的引用入了两次。

最有可能的解决方案是在插入之前进行深度克隆。请考虑使对象不可变,以简化代码的同步和可读性。

源语言:

最可能的原因是您的日志记录代码未正确同步。由于看起来您希望以原子方式发生 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; 
    } 
} 
相关文章: