2016-09-21 40 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刪除過程。

在這裏,我需要確保校驗碼allProcessDetails.ContainsKey(processDetails.ProcessID)UpdateProcess不與刪除代碼allProcessDetails.Remove(processDetails.Key)OnTimerElapsed

衝突,因爲按我的理解加把鎖將阻止從使用相同的代碼創建另一個線程訪問序列,但在這裏字典是由不同的線程訪問由不同的代碼序列(計時器和事件處理程序)創建的

那麼,如何防止事件處理程序方法訪問當前可以在計時器方法中訪問的鍵去除。

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