Let's suppose I have the following piece of code:
IEnumerable<string> allKeys = _cache.Select(o => o.Key);
Parallel.ForEach(allKeys, key => _cache.Remove(key));
As you can see, I'm retrieving all the keys in _cache
, storing them in my local variable allKeys
, and then concurrently removing all the keys from _cache
.
I would like however, to do it one single line. So what comes to mind is:
Parallel.ForEach(_cache.Select(o => o.Key), key => _cache.Remove(key));
But the statement _cache.Select(o => o.Key)
would be called on each loop iteration, therefore retrieving different amount of elements each time (because I'm deleting them at the same time).
Is the latter line of code safe?
Does _cache.Select(o => o.Key)
in loop statements, only get called once, and then each iteration uses the original result, or is it processed in every iteration step?
As you can see, I'm retrieving all the keys in _cache, storing them in my local variable allKeys
No, you don't. Due to something called deferred execution, all you store is the command to get all your keys. You need to materialize this command to actually do what you think you do:
var allKeys = _cache.Select(o => o.Key).ToList();
That said: Is your cache thread safe? Why does it not feature a Clear method? Getting all keys and removing it by using multi threading seems like a not-so-great-idea.
If you insist to have it all in one line, you could use PLINQ:
_cache.Select(o => o.Key).AsParallel().ForAll(key => _cache.Remove(key));
But again: this seems to be a bad idea.
First off, both codes are the same. There is no difference if you have a temporary variable or not.
Second: This code is flawed.
allKeys
, the underlying data - in your case _cache
- is being iterated. In combination with the remove, this won't work._cache
most likely is a normal dictionary or something similar. In other words, it is not thread safe. UPDATE: According to a comment, it is of type ObjectCache
and that type is indeed thread-safe. So this issue doesn't occur in your specific case.Would it not be more efficient to Dispose
of your existing _cache object and just recreate it, rather than removing every item individually?
Saves querying and looping...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With