He creado un caché usando la clase MemoryCache. Le agrego algunos elementos, pero cuando necesito volver a cargar el caché, quiero borrarlo primero. ¿Cuál es la forma más rápida de hacer esto? ¿Debería recorrer todos los elementos y eliminarlos uno a la vez o hay una forma mejor?¿Cómo borrar MemoryCache?
Respuesta
Dispose
MemoryCache existente y crea un nuevo objeto MemoryCache.
También podría hacer algo como esto:
Dim _Qry = (From n In CacheObject.AsParallel()
Select n).ToList()
For Each i In _Qry
CacheObject.Remove(i.Key)
Next
var cacheItems = cache.ToList();
foreach (KeyValuePair<String, Object> a in cacheItems)
{
cache.Remove(a.Key);
}
Esto tiene el mismo riesgo que la respuesta de @ Tony; por favor mira mi comentario debajo de eso. – TrueWill
@TrueWill ¿Quién es o era @Tony? –
@AlexAngas - Puede haber cambiado su nombre a magritte. Ver también http://stackoverflow.com/questions/4183270/how-to-clear-the-net-4-memorycache/22388943#22388943 – TrueWill
La solución es:
versiónList<string> cacheKeys = MemoryCache.Default.Select(kvp => kvp.Key).ToList();
foreach (string cacheKey in cacheKeys)
{
MemoryCache.Default.Remove(cacheKey);
}
De la [documentación] (http://msdn.microsoft.com/en- us/library/system.runtime.caching.memorycache.getenumerator.aspx): _Recuperar un enumerador para una instancia de MemoryCache es una operación de uso intensivo y de bloqueo de recursos. Por lo tanto, el enumerador no se debe usar en aplicaciones de producción. – TrueWill
No creo que esto sea lo mismo que recuperar un enumerador. Esto es bastante rápido y no enumera nada. Aún así ... me gusta deshacerme del caché. – hal9000
@emberdude Es exactamente lo mismo que recuperar un enumerador. ¿Qué le parece la implementación de 'Select()'? – RobSiklos
un poco de mejora de la respuesta Magritte.
var cacheKeys = MemoryCache.Default.Where(kvp.Value is MyType).Select(kvp => kvp.Key).ToList();
foreach (string cacheKey in cacheKeys)
{
MemoryCache.Default.Remove(cacheKey);
}
Si el rendimiento no es un problema, este bonito de una sola línea hará el truco:
cache.ToList().ForEach(a => cache.Remove(a.Key));
El problema con la enumeración
El MemoryCache.GetEnumerator() Remarks section advierte: "Recuperación de un enumerador para una La instancia de MemoryCache es una operación de bloqueo y de uso intensivo de recursos. Por lo tanto, el enumerador no se debe usar en aplicaciones de producción ".
He aquí por qué, se explica en pseudocódigo de la GetEnumerator() aplicación:
Create a new Dictionary object (let's call it AllCache)
For Each per-processor segment in the cache (one Dictionary object per processor)
{
Lock the segment/Dictionary (using lock construct)
Iterate through the segment/Dictionary and add each name/value pair one-by-one
to the AllCache Dictionary (using references to the original MemoryCacheKey
and MemoryCacheEntry objects)
}
Create and return an enumerator on the AllCache Dictionary
Desde la implementación divide la memoria caché en varios objetos de diccionario, que debe reunir todo en una sola colección con el fin de la mano volver un enumerador. Cada llamada a GetEnumerator ejecuta el proceso de copia completo detallado anteriormente. El diccionario creado recientemente contiene referencias a la clave interna original y los objetos de valor, por lo que sus valores de datos en caché no se duplican.
La advertencia en la documentación es correcta. Evite GetEnumerator(), incluidas todas las respuestas anteriores que utilizan consultas LINQ.
Una solución mejor y más flexible
Aquí es una manera eficiente de borrar la memoria caché que simplemente se basa en la infraestructura existente de seguimiento del cambio. También proporciona la flexibilidad para borrar todo el caché o solo un subconjunto con nombre y no tiene ninguno de los problemas mencionados anteriormente.
// By Thomas F. Abraham (http://www.tfabraham.com)
namespace CacheTest
{
using System;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.Caching;
public class SignaledChangeEventArgs : EventArgs
{
public string Name { get; private set; }
public SignaledChangeEventArgs(string name = null) { this.Name = name; }
}
/// <summary>
/// Cache change monitor that allows an app to fire a change notification
/// to all associated cache items.
/// </summary>
public class SignaledChangeMonitor : ChangeMonitor
{
// Shared across all SignaledChangeMonitors in the AppDomain
private static event EventHandler<SignaledChangeEventArgs> Signaled;
private string _name;
private string _uniqueId = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture);
public override string UniqueId
{
get { return _uniqueId; }
}
public SignaledChangeMonitor(string name = null)
{
_name = name;
// Register instance with the shared event
SignaledChangeMonitor.Signaled += OnSignalRaised;
base.InitializationComplete();
}
public static void Signal(string name = null)
{
if (Signaled != null)
{
// Raise shared event to notify all subscribers
Signaled(null, new SignaledChangeEventArgs(name));
}
}
protected override void Dispose(bool disposing)
{
SignaledChangeMonitor.Signaled -= OnSignalRaised;
}
private void OnSignalRaised(object sender, SignaledChangeEventArgs e)
{
if (string.IsNullOrWhiteSpace(e.Name) || string.Compare(e.Name, _name, true) == 0)
{
Debug.WriteLine(
_uniqueId + " notifying cache of change.", "SignaledChangeMonitor");
// Cache objects are obligated to remove entry upon change notification.
base.OnChanged(null);
}
}
}
public static class CacheTester
{
public static void TestCache()
{
MemoryCache cache = MemoryCache.Default;
// Add data to cache
for (int idx = 0; idx < 50; idx++)
{
cache.Add("Key" + idx.ToString(), "Value" + idx.ToString(), GetPolicy(idx));
}
// Flush cached items associated with "NamedData" change monitors
SignaledChangeMonitor.Signal("NamedData");
// Flush all cached items
SignaledChangeMonitor.Signal();
}
private static CacheItemPolicy GetPolicy(int idx)
{
string name = (idx % 2 == 0) ? null : "NamedData";
CacheItemPolicy cip = new CacheItemPolicy();
cip.AbsoluteExpiration = System.DateTimeOffset.UtcNow.AddHours(1);
cip.ChangeMonitors.Add(new SignaledChangeMonitor(name));
return cip;
}
}
}
Parece una implementación de la funcionalidad regional faltante. – Jowen
Muy agradable. He estado tratando de implementar algo utilizando monitores y guids de caché de memoria encadenada, pero estaba empezando a ponerse un poco feo cuando traté de ajustar la funcionalidad. – Chao
No recomendaría este patrón para uso general. 1. Es lento, no es culpa de la implementación, pero el método de eliminación es extremadamente lento. 2. Si expulsa elementos de la memoria caché con un vencimiento, aún se llama a Change Monitor. 3. Mi máquina estaba tragando toda la CPU, y demorando mucho tiempo en borrar 30k elementos de la caché cuando estaba ejecutando pruebas de rendimiento. Algunas veces después de esperar más de 5 minutos acabo de matar las pruebas. –
Parece que hay un método Trim.
Así que para borrar todos los contenidos que sólo harías
cache.Trim(100)
EDIT: después de cavar un poco más, parece que mirar en el ajuste no es digno de su tiempo
Funcionó a través de esto, y en función de ello , escribió un método claro paralelo ligeramente más efectivo:
public void ClearAll()
{
var allKeys = _cache.Select(o => o.Key);
Parallel.ForEach(allKeys, key => _cache.Remove(key));
}
- 1. MemoryCache UpdateCallback no funciona
- 2. ¿Cómo sabe MemoryCache cuánta memoria usa?
- 3. ¿Puedo iterar sobre .NET4 MemoryCache?
- 4. MemoryCache con soporte de regiones?
- 5. Uso de varias instancias de MemoryCache
- 6. ASP.NET Cache class vs. MemoryCache class
- 7. ¿Cómo borrar Viewstate?
- 8. Cómo borrar: ambos; ¿correctamente?
- 9. ¿Cómo borrar una cadena?
- 10. ¿Cómo borrar ImageView correctamente?
- 11. Cómo borrar una matriz
- 12. ¿Cómo borrar un diccionario?
- 13. cómo borrar JTable
- 14. Cómo borrar ostringstream
- 15. Cómo borrar un UIWebView
- 16. cómo borrar el montón?
- 17. .Net 4 MemoryCache Leaks with Concurrent Garbage Collection
- 18. ¿Cómo borrar $ Error en PowerShell?
- 19. Cómo borrar carriles tablas tabla
- 20. Cómo borrar un filtro - AngularJS
- 21. Cómo borrar jquery validar errores
- 22. Cómo "borrar" elementos absolutamente posicionados
- 23. Cómo borrar caché de Smarty
- 24. Minificar, ¿cómo borrar el caché?
- 25. ¿Cómo borrar toda la matriz?
- 26. Borrar Función
- 27. Borrar texto seleccionado ComboBox
- 28. Botón Borrar en UITextView
- 29. WPF TreeView Borrar selección
- 30. Cómo borrar una cola en Oracle AQ
Inicialmente usé MemoryCache.Default, haciendo que Dispose me causara un poco de dolor. Aún así, Dispose terminó siendo la mejor solución que pude encontrar. Gracias. – LaustN
@LaustN ¿Puede explicar el "dolor" causado por MemoryCache.Default? Actualmente uso MemoryCache.Default ... La documentación de MemoryCache de MSDN me hace preguntarme si se recomienda deshacer y recrear: "No cree instancias de MemoryCache a menos que sea necesario. Si crea instancias de caché en aplicaciones cliente y Web, las instancias de MemoryCache deberían crearse temprano en el ciclo de vida de la aplicación ". ¿Esto se aplica a .Default? No digo que utilizar Dispose sea incorrecto, sinceramente solo estoy buscando una aclaración sobre todo esto. –
Pensé que valía la pena mencionar que 'Dispose' _does_ invoca cualquier' CacheEntryRemovedCallback' adjunta a los elementos actuales almacenados en caché. –