2016-10-20 5 views
1

私はC#で作業しています。私はアプリケーションを同期させるためのメカニズムを探しています。どのような同期を使用できますか?

私はアプリケーションで異常を管理し、マルチスレッドで作業する機能を持っています。異常が発生すると、関数が呼び出され、何らかの処理が行われ、ユーザーに確認を求められます。

最初は進行中で、私は(関数が最初のために実行された)後の最初のと何もしないのを待ちたいている間に、新たな異常が発生した場合

どのように適切にそれを行うことができますか?

マイドラフト:

private void onAnomaly(enumAnomaly err) 
{ 
    if (anomalyInProgress) 
     //wait 
     return; 
    else 
     anomalyInProgess = true; 
     //do something 
     anomalyInProgess = false; 
} 
+0

[ロック](https://msdn.microsoft.com/en-us/library/c5kehkcz.aspx) – Rob

+0

ロックは最初のものを待っていますが、コードを実行した後 –

+0

私はこの部分を取得しませんでした - '(最初に関数が実行された後に)何もしない '?最初の異常が処理されている間に、新しい異常が処理されるまで待つことを望みますか?最初の異常が終了すると、新しく到着した異常の処理を開始する必要があります。私は理解して正しいですか? – RBT

答えて

0

あなたはInterlocked.Exchange methodを使用することができます。

ご意見に応じてを編集するには、他の機能を待たなければなりません。これを行うには、ロックオブジェクトを追加します。異常が発生すると

private int anomalyInProgress = 0; 
private Object _lock = new Object(); 

private void onAnomaly(enumAnomaly err) 
{ 
    //Here, the value of anomalyInProgress will be set to 1, but 
    // Exchange return the value before the change. 
    // So if it was 0 before, it means nobody is already executing this code 
    //and we can safely enters 
    if (0 == Interlocked.Exchange(anomalyInProgress, 1)) 
    { 
     lock (_lock) 
     { 
      //do something 

      //we reset the value of anomalyInProgress so the next one can enter in safely 
      Interlocked.Exchange(anomalyInProgress, 0) 
     } 
    } 
    else 
    { 
     //I cannot take the lock directly, because I could be taking it before the 'True' condition. 
     Threading.Thread.Sleep(1) 
     lock (_lock) //This will wait for the 'True' condition to finish 
     { 
     } 
    } 
} 
+0

私がAmey Kamatに言ったように、 'ロック'は '何かをする'を2回(あるいはそれ以上)実行します。 –

+0

完了したらanomalyInProgressを0に戻すことを忘れないでください。そうしないと、将来のコールも破棄されます。 – FacticiusVir

+0

@SuperPeanutこのソリューションをテストするだけで、最初の機能を待っているとは感じられません。たぶん私はこのソリューションを 'ManualResetEvent'と混在させることができますが、効率的かつ安全ですか? –

-1

、あなたが呼び出す関数は、このことができます

object lockObj = new object(); 
lock(lockObj) 
{ 
    //function called once anomaly raised 
} 

希望をロックすることができます。

+0

私は間違っているかもしれませんが、私のためにロックは' '一度異常が発生しました 'という関数を待っています。最初のコールが2番目のコールを終了すると、コールを開始します。それはほとんど私が欲しいが、私は何度も機能と呼ぶべきものだ –

0

私は、ロックを持つ方法を見つけ、多分ベストではないが、それは

private object anomalyLock = new object(); 
private Queue<enumAnomaly> anomalyQueue = new Queue<enumAnomaly>(); 

private void onAnomaly(enumAnomaly err) 
{ 
    anomalyQueue.Enqueue(err); 

    lock (anomalyLock) 
    { 
     if (anomalyQueue.Count == 0) 
      return; 

     //do something 

     // UserAck 

     anomalyQueue.Clear(); 
    } 
} 

を動作しているよう最善の方法はありますか?

+2

危険な!ロックを取る前に、2つの異常が同時にエンキューされることがあります。キューの前面にあるものだけを処理してから、キュー全体をクリアします。キュー内の他の異常を処理することさえできないかもしれません。私は '/ do something'セクションでキューをどのように処理しようとしているのかを明らかにしない限り、これは可能です。それでも、元の問題文は、前の異常が完全に処理されない限り、何らかの異常処理を開始したくないという事実でした。ではない? – RBT

+0

その場合、ロックの前に1つ以上の異常があるかどうかは気にしません。しかし、あなたは正しく、ユーザーのackと 'queue.Clear'の間に異常が起きると、リスクがあります。しかし、私はもっと良いことはありません –

+0

私はInterlocked.exchangeで提供したソリューションを試しましたか?私はそれがあなたが必要とするものを正確に行うと思います... –

関連する問題