2012-04-27 8 views
0

あるスレッドで処理され、キューに入れられるデータがあるので、別のスレッドが情報をデキューして、その上でいくつかのアクションを実行しています。ここでデータを保持しないC#での同時静的キュー

私は私が

MyConcurrentQueue._Queue.TryDequeue(out _Rule) 
を使用デキューする

MyConcurrentQueue.EnqueueRuleTrigger(_Rule); //We're done enqueue the rule 

を使用するルールをエンキューしたい場合、私は

MyConcurrentQueue._Queue = new ConcurrentQueue<cRule>(); 

を持っているのApplication_Start上のキュー

public static class MyConcurrentQueue 
{ 
    public static ConcurrentQueue<cRule> _Queue; 

    public static void EnqueueRuleTrigger(cRule _Rule) 
    { 
     MyConcurrentQueue._Queue.Enqueue(_Rule); 
    } 
} 

です

は私がタイトループ内で他の後に2つのアイテム、1をキューに入れた場合、最初のデキュー[別の非同期スレッド]の時間によって、ログファイル内のデータはもう

をエンキューと一致しなかったことに気づいエンキューの間にスリープ状態にすると、ログが正しい値を読み込みます。おそらく、1つのアイテムがデキューされ、別のアイテムがデキューされ、デキューされるためです。

キューは静的であり、キューのコピーではなく_Ruleへの参照が格納されているためです。どのように私はこれを修正することができますか?キューを複数のスレッドからアクセスできるようにする必要があります。そのため、最初は静的にしました。

ありがとうございます。ここでEDIT

が、これは私のログファイル

で私のエンキューおよびログおよびデキューとログロジックこれは別のスレッド

if (MyConcurrentQueue._Queue.TryDequeue(out _Rule)) 
       { 
... some logic 
    File.WriteAllText(@"C:\Default\New.txt", AllText + "\r\nDequeue Alert:" + 
_Rule.AlertID + ":" + _Rule.TriggerStartTime + "-" + _Rule.TriggerEndTime); 
    } 

にある

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); 

} 

です

エンキューアラート:64c88289-58a1-499b-ade9-3 fa69a32cf47:2012/04/27 12:00:00 2012年4月27日5:00:00 PM

エンキューアラート:64c88289-58a1-499b-ade9-3fa69a32cf47:4/28/2012 2:00 :00 PM-4/28/2012 9:00:00 PM

デキューアラート:64c88289-58a1-499b-ade9-3fa69a32cf47:2012/04/28 2:00:00 PM-4/28/2012 9 :00:00 PM

デキューアラート:64c88289-58a1-499b-ade9-3fa69a32cf47:2012年4月28日2時00分〇​​〇秒PM-4/2012分の28午前九時00分00秒PM

+0

これまでのところ、特にコードに間違いはありませんが、何が失敗しているかはあまり明確ではありません。補足:サンプルコードを投稿する場合、つまり小文字(cRule)で始まる名前クラスではなく、C#のコーディングガイドラインに従うことを検討してください。 –

+0

私はコーディングのガイドラインをチェックアウトします:) 申し訳ありません申し訳ありません、私はエンキュー時に、私はデキュー時にエントリを作るがあります。私は2つのアイテムを持っている場合は は、AとB A.value = 1 B.value = 2 私は エンキュー値1 デキュー値2 エンキュー値2 デキュー値のように見えるのログファイルを持つことになりますと言います2 私はAとBを1つのスレッドのループにエンキューし、別のスレッドasynchでデキューすることを検討します。タイトなループで2番目のエンキューが問題であると思われます。最初のエンキューの値が上書きされます。私がエンキューの間にスリープ状態を置くと、ログは適切な値を読み込みます。 – Jordan

+0

これは、最終的に私が何らかの種類の参照問題を抱えていると信じるようになります。したがって、ログの値が正しければ、私は一度エンキューしてデキューします。[ログが書き込まれる前に2番目のエンキューが発生しないように、そこに睡眠を入れます。 基本的にスリープなしでは、最初のオブジェクトの最初のデキューには2番目のオブジェクトの値があります。[2番目のオブジェクトと同じ] – Jordan

答えて

1

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

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

オリジナル:

ほとんどlikly理由は、あなたのロギングコードが正しく同期していないです。 2つのアクションが原子的に(Enqueue + LogまたはDequeue + Log)起こるように見えるので、両方の操作の周りに適切なロックを追加する必要があります。そうでなければ、QueueおよびLogへの呼び出しの順序はセミランダムです。また、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; 
    } 
} 
+0

私の更新されたコードを見てください。エンキュー直後とデキュー直後にロギング操作を行い、出ているデータが正しくないことがわかります。しかし、2つのエンキューの間にスリープを追加すると、ログに適切なデータが得られます。私の疑念は、最初のデキューが発生するまでに2番目のエンキューが既に起こっていることです。[それはタイトなループにあります] _Ruleはコピーされたvaleの代わりに参照または何かのように扱われているので、それらはすべて1つの参照を共有しています。ありがとう – Jordan

+0

私はTryDequeへの呼び出しで何らかの共有メンバー変数を使用していないと思います(デキュー呼び出しを参照)。それ以外の場合は、適切なロックが必要です。あなたのトレースがエントリの任意の順序になるかもしれないことに注意してください... –

+0

私はその部分を投稿すべきです残念です 'Rule _Rule = new Rule(); if(MyConcurrentQueue._Queue.TryDequeue(out _Rule)) ' スレッドが呼び出されるたびに、新しいルールを作成する必要があります。 – Jordan

関連する問題