2016-09-21 2 views
0

メソッドを持つクラスが非常にX分実行され、別のメソッドがイベントハンドラを呼び出しました。どちらも静的リストのステータスを変更します。以下は静的変数をロックする - タイマーとイベントハンドラ

それはそれはいくつかのロジックを行いますと、プロセスが存在しない場合、それはと同じプロセスを更新します(存在する場合)イベントハンドラメソッドは、プロセスのためにそれをチェックするコード

public class DatabaseOps 
{ 
    private static Timer timer = null; 

    private static IDictionary<int, Model.Process> allProcessDetails = new Dictionary<int, Model.Process>(); 

    public DatabaseOps() 
     { 
      if (timer.IsNull()) 
      { 
       timer = new Timer(5000); 
       timer.Elapsed += new ElapsedEventHandler(OnTimerElapsed); 
       timer.Enabled = true; 
       timer.AutoReset = true; 
       timer.Start(); 
      } 
     } 

     // Timer event 
     private async void OnTimerElapsed(object sender, ElapsedEventArgs e) 
     { 
      foreach (var processDetails in tempAllProcessDetails) 
      { 
       // Some logic 
       allProcessDetails.Remove(processDetails.Key); 
       await Task.Run(() => SendProcess(processDetails.Value)); 
      } 
     } 

     // Method invoked from event handler 
     public void UpdateProcess(Model.Process processDetails) 
     { 

      if (!allProcessDetails.ContainsKey(processDetails.ProcessID)) 
      { 
       // Add process to allProcessDetails 
       // Some logic 
      } 
      else 
      { 
       // Modify existing process in allProcessDetails 
       // Some logic 
      } 
     } 
} 

です新しい論理。

タイマはX間隔ごとに実行され、すべてのプロセスの現在のステータスを外部システムに送信し、プロセスをallProcessDetailsから削除します。私はUpdateProcessにチェックコードallProcessDetails.ContainsKey(processDetails.ProcessID)を確保する必要がある。ここ

は、ロックを追加私の理解あたりとしてOnTimerElapsed

に削除コードallProcessDetails.Remove(processDetails.Key)と競合しない同じコードを使用して作成され、別のスレッドからのアクセスをブロックしますここでは、別のコードシーケンス(タイマーとイベントハンドラ)から作成された別のスレッドによって辞書にアクセスします。

したがって、イベントハンドラメソッドが現在タイマーメソッドでアクセス可能な同じキーにアクセスするのを防ぐにはどうすればよいですか除去のために。

+0

あなたが本当に別の 'OnTimerElapsed'かかわらず、前の' OnTimerElapsed'は、実行が完了したのを発射する必要がありますか?また、 'System.Timers.Timer'(' System.Threading.Timer'と同様に)は、スレッドプールスレッド上でコールバックが実行されるマルチスレッドタイマーです。だから、上記を知って、なぜあなたは 'Task.Run'が必要ですか? –

+0

@AlexeyGroshev私は次のタイマーイベントの前にタスクが完了するのを待っていません。また、Task.Runより前のタイマーイベントで実装されたロジックは、タイマーインターバルよりも時間がかかりません。 –

答えて

0

だけConcurrentDictionaryを使用します。

private static IDictionary<int, Model.Process> allProcessDetails = new ConcurrentDictionary<int, Model.Process>();