2013-10-01 3 views
3

Я использую словарь для сбора событий в многопоточном приложении, используя блокировку, когда добавляю событие и не использую его при поиске. Каждый час или около того я запускаю очистку событий старше определенного времени. Очень простой и он работает.Использование LINQ ToDictionary с ConcurrentDictionary

Я хотел бы перейти к ConcurrentDictionary, чтобы удалить блокировки, и я подумал, что мне просто нужно добавить «Concurrent» и изменить Add to TryAdd. Но тогда я понес в ошибке, что LINQ возвращает только ToDictionary. Я могу obviusly не использовать LINQ, но я был любопытным, знаю, есть ли что-то, что я могу сделать, чтобы сохранить его. И что еще важнее, есть ли что-то, что я еще должен рассмотреть, прежде чем переходить на ConcurrentDictionry?

public class messageResult 
     { 
      public Result result; 
      public DateTime receivedTime; 
     } 


public Dictionary<Guid, messageResult> events = new Dictionary<Guid, messageResult>(); 


lock (events) 
      { 
       events = events.Where(p => p.Value.receivedTime >= t).ToDictionary(p => p.Key, p => p.Value); 
      } 

Благодаря

+1

Почему вы не используете 'System.Runtime.Caching.MemoryCache'? –

+1

«* используя блокировку, когда я добавляю событие и ** не использую его ** при поиске одного *« Замки не работают таким образом, вы должны блокировать чтение, чтобы предотвратить запись во время чтения. Однако вы можете делать то, что хотите (разрешить несколько читателей и один писатель), используя вместо этого [ReaderWriterLockSlim] (http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx) это позволит вам иметь много читателей, которые все останавливаются, когда один писатель хочет писать. –

+0

@ L.B спасибо за предложение, но каковы преимущества перед моим общим экземпляром Dictionary? –

ответ

0

Это выглядит как ToDictionaryextension method не так сложно, и вы можете создать свою собственную версию.

Но обратите внимание, что ToDictionary возвращает новый объект, пока вы хотели бы иметь один словарь и делиться им между вашими темами.

Вы не должны блокировать изменяемую переменную (и вы также меняете фактическую ссылку на events), создайте приватную переменную readonly и используйте ее для блокировки.

+0

Можете ли вы разработать «создать частную переменную readonly и использовать ее для блокировки»? Я не понимаю, как я могу использовать переменную readonly в этом контексте. –

+0

http://stackoverflow.com/questions/5053172/why-does-the-lock-object-have-to-be-static –

0

ToDictionary возвращает новый экземпляр ... который отличается от вашего общего экземпляра.

Вы хотите изменить общий экземпляр и должен написать код, который делает это:

foreach(var kvp in events.Where(...).ToList()) 
{ 
    var val = kvp.Value; 
    events.TryRemove(kvp.Key out val); 
} 
+0

Да, вы right, он возвращает новый экземпляр, но поскольку он находится в замке, он должен работать (на самом деле он работает). Является ли неправильным то, что я делаю или просто неэффективно? –

+0

Кстати, ваше предложение состоит в том, чтобы использовать ConcurrentDictionay, но зачем же итерации элементов, которые вы конвертируете в список, не могу ли я итерации непосредственно через элементы ConcurrentDictionary и TryRemove истекших? –

Смежные вопросы