I have a static dictionary which holds authentications for a web service. I'm running a timer (hence the TimerCallBack sig on the method below) to remove those authentications which have been dormant for a period.
I'm not quite sure of the locking behaviour I need in relation to linq. Here's my code thus. I'm slightly concerned that I may affect performance by using too many locks. e.g. Would it be better to just take a single writelock and no readlocks (even if no authentications had expired)?
private static void RemoveExpiredAuthentications(object o)
{
var expired = from a in _authentications
whe开发者_开发技巧re a.Value.LastAccessed.AddSeconds(expired_interval_secs) < DateTime.Now
select a;
using (new ReadLock(dictionaryLock)) {
expired.Select(e => {
using (new WriteLock(dictionaryLock)){
_authentications.Remove(e.Value.Token);
}
}
}
}
Many thanks
Simon
I would suggest working out everything you want to remove first, and then doing it all in one lock:
var itemsToRemove = expired.Select(e => e.Value.Token).ToList();
using (new WriteLock(dictionaryLock))
{
foreach (var removal in itemsToRemove)
{
_authentications.Remove(removal);
}
}
Aside from anything else, this means you won't be trying to remove an item from the dictionary while iterating over it.
(Just to check: is the key to each entry the same as the Token
property value? If so, you can just use e.Key
rather than e.Value.Token - that may be somewhat clearer.)
foreach (var auth in expired) {
using (new WriteLock(dictionaryLock)){
_authentications.Remove(e => e.Value.Token);
};
}
or
using (new WriteLock(dictionaryLock)){
foreach (var auth in expired) {
_authentications.Remove(e => e.Value.Token);
};
}
if you ndeed to lock until all items are removed.
Sometimes Linq is not the best choice, although, I have to admit, rarely.
精彩评论