2011-10-03 2 views
0

У меня есть форма с элементом управления, чтобы отображать некоторые пользовательские объекты. В форме я подписываюсь на событие AddObject, которое добавляет объекты в список ToAdd, когда они входят с сервера. Я настраиваю таймер для запуска каждые 10 секунд, чтобы скопировать объекты из списка ToAdd в список отображения (было более эффективно добавлять элементы навалом в элемент управления, чем 1 за раз, когда они вошли), который связан с контроль над моей формой, затем я очищаю список ToAdd. Безопасно ли иметь замок внутри BeginInvoke? Есть ли лучший способ сделать это?Безопасно ли иметь блокировку() внутри вызова BeginInvoke?

 private System.Threading.Timer aTimer; 
     private readonly Object sync = new Object(); 
     List<object> ToAdd = new List<object(); 
     List<object> Display = new List<object(); 

     private void Init() 
     { 
      TimerCallback tcb = IntermittentProcessMessages; 
      aTimer = new System.Threading.Timer(tcb, null, 1000, 100); 
      Server.MessageReceived += AddObject; 
     } 

     private void AddObject(object t) 
     { 
      lock (sync) 
      { 
       try 
       { 
        ToAdd.Add(t); 
       } 
       finally() {} 
      } 
     } 


     private void IntermittentProcessMessages(object source) 
     { 
      try 
      { 
       if (this.IsHandleCreated == false) 
       { 
        return; 
       } 
       this.BeginInvoke((Action)delegate() 
       { 
        lock (sync) 
        { 
         if (ToAdd.Count > 0) 
         { 
          ToAdd.ForEach(f => Display.Add(f)); 
          ToAdd.Clear(); 
         } 
        } 
       } 
      } 
      finally(){} 
    } 
+0

Это выглядит хорошо для меня. – Gabe

+0

Вы используете тот же объект синхронизации в AddObject и BeginInvoke. Используйте два разных объекта синхронизации, чтобы они не были заблокированы друг для друга. –

+0

@UnmeshKondolikar, Они * должны * блокировать друг друга, так как они защищают список 'Display'. –

ответ

1

Да, это безопасно. Технически блокировка не находится в BeginInvoke, но в анонимной функции, созданной с delegate.

Некоторые примечания:

  • List<T> имеет AddRange метод, который является более эффективным, чем кратное Add.
    Использовать его как Display.AddRange(ToAdd);
  • Делегат в IntermittentProcessMessages не подпадает под попытку, так как BeginInvoke немедленно возвращается.
Смежные вопросы