tienes que estar preparado para recorrer y tal vez llamar a la Func
más de una vez (lo mismo que con la sobrecarga de GetOrAdd
que utiliza uno). Esto significa que si el Func
tiene efectos secundarios, no parecerá ser atómico desde el exterior. Realmente, Func
s no deben tener efectos secundarios, pero siempre tienen algún costo por lo que la posibilidad de repetición de llamadas no puede ser ignorada:
public static bool TryUpdate<TKey, TValue>(
this ConcurrentDictionary<TKey, TValue> dict,
TKey key,
Func<TValue, TValue> updateFactory)
{
TValue curValue;
while(dict.TryGetValue(key, out curValue))
{
if(dict.TryUpdate(key, updateFactory(curValue), curValue))
return true;
// if we're looping either the key was removed by another thread,
// or another thread changed the value, so we start again.
}
return false;
}
Como se ha dicho, ya que puede bucle, es sólo atómica como se observa desde el exterior si no hay efectos secundarios en el Func
.
(Editar: Eliminando un atajo potencial que en realidad es demasiado tenso como para ser usado en general, y que probablemente muerda a alguien que lo probó).
No hay un método que lo haga. ¿Ha considerado agregar un valor especial si la clave no existe y tratar ese valor como si la entrada no estuviera presente? – dtb
@dtb Dado que estoy escribiendo un contenedor para esta clase, no es posible encontrar una clave no válida. Puedo pedirlo específicamente, pero esa no sería mi primera opción. –
En realidad, si está escribiendo un contenedor, en realidad puede almacenar elementos que envuelven el valor, lo que le permite crear su propio valor especial de lápida. Sin embargo, agregaría un costo a cada uso individual. –