Mam rozpoczęciem pracy z niektórych kodu .NET 3.5 i znaleźć następującą metodę rozszerzenia wykorzystywane do pamięci podręcznej ::Dla .NET 3.5 w jaki sposób można utworzyć wątek bezpieczny lub dodać pamięć podręczną?
public static TValue GetOrAdd<TKey, TValue>(this Dictionary<TKey, TValue> @this, TKey key,Func<TKey,TValue> factory,bool useLocking)
{
TValue value;
if([email protected](key,out value))
{
if (useLocking)
{
lock ((@this as ICollection).SyncRoot)
{
if ([email protected](key, out value))
{
@this[key] = value = factory(key);
}
}
}
else
{
@this[key] = value = factory(key);
}
}
return value;
}
Pamięć podręczna w pytaniu jest osadzone przez kluczami tekstowymi, iz useLocking = true. Jest zawsze dostępny za pomocą tej metody (nie ma bezpańskich TryGetValue
). Nie ma również problemu z korzystaniem z właściwości SyncRoot
, ponieważ słownik jest prywatny i nie ma innego miejsca, w którym jest używany. Podwójne blokowanie jest niebezpieczne, ponieważ słownik nie obsługuje odczytu podczas jego zapisywania. Chociaż technicznie nie zgłoszono jeszcze żadnego problemu, ponieważ produkt nie został wysłany, uważam, że takie podejście doprowadzi do warunków wyścigowych.
Przejście do
Dictionary<,>
DoHashtable
. Stracimy bezpieczeństwo typu, ale będziemy w stanie obsłużyć model współbieżności, o który nam chodzi (1 autor, wielu czytelników).Usuń zewnętrzną wartość TryGetValue. W ten sposób każda lektura wymaga zdobycia zamka. Jest to potencjalnie złe z punktu widzenia wydajności, ale uzyskanie niekwestionowanej blokady powinno być dość tanie.
Obie są dość brzydkie. Czy ktoś ma lepszą sugestię? Gdyby to był kod .NET 4, po prostu przełączyłem go na ConcurrentDictionary
, ale nie mam tej opcji.
Yargh! Całkowicie niepowiązany ... ale nie pisz kodu używając @this. Jesteś w statycznej metodzie; nie próbuj sprawiać, by wyglądała jak metoda instancji. –
to nie jest mój kod! Gdyby to był mój kod, dodałem walidację argumentów. –