0

そのため、あるスレッドで処理されてキューに入れられたデータがあり、別のスレッドが情報をデキューし、それに対していくつかのアクションを実行しています。

ここにキューがあります

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 つの項目を 1 つずつエンキューすると、最初のデキュー [個別の非同期スレッド] の時点までに、ログ ファイル内のデータがエンキューと一致しなくなることに気付きました。

エンキューの間にスリープを入れると、ログは正しい値を読み取ります。おそらく、あるアイテムが入れられ、キューから取り出され、別のアイテムが入れられ、キューから取り出されたためです。

これは、キューが静的であり、_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 ~ 2012 年 4 月 27 日 5:00:00 PM

エンキュー アラート:64c88289-58a1-499b-ade9-3fa69a32cf47: 2012 年 4 月 28 日午後 2:00:00 ~ 2012 年 4 月 28 日午後 9:00:00

デキュー アラート:64c88289-58a1-499b-ade9-3fa69a32cf47: 2012 年 4 月 28 日午後 2:00:00 ~ 2012 年 4 月 28 日午後 9:00:00

デキュー アラート:64c88289-58a1-499b-ade9-3fa69a32cf47: 2012 年 4 月 28 日午後 2:00:00 ~ 2012 年 4 月 28 日午後 9:00:00

4

1 に答える 1

1

編集:同じオブジェクトを変更して2回目にエンキューするよりも、オブジェクトをエンキューすることに問題があるようです。その結果、デキュー中に、2 番目のオブジェクトが最初のオブジェクトをオーバーライドして 2 回挿入されたように見えますが、実際には同じオブジェクトへの参照が 2 回挿入されました。

最も可能性の高い解決策は、挿入前にディープ クローンを作成することです。同期を簡素化し、コードを読みやすくするために、オブジェクトを不変にすることを検討してください。

オリジナル:

最も可能性の高い理由は、ロギング コードが適切に同期されていないことです。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; 
    } 
} 
于 2012-04-27T04:36:33.060 に答える