Minha pergunta é semelhante a esta , mas as respostas apenas explicam por que as coisas acontecem da maneira que acontecem, e não como realmente alcançar a solução desejada.
Neste momento, ao definir
var options = new MemoryCacheEntryOptions()
{
// After x minutes of non-access, remove
SlidingExpiration = TimeSpan.FromMinutes(x),
}
.RegisterPostEvictionCallback(OnCacheItemRemoved);
Um cacheItem só será removido ao acessá -lo em um timepoint t1
> t0 + x'
. Isso significa que se eu não acessar mais o item depois desse ponto, ele também nunca será removido do cache.
Eu poderia definir uma expiração absoluta, sim, mas isso anularia a janela deslizante. Se eu quisesse que ele ficasse na memória se ainda estivesse sendo acessado, ele seria despejado devido à expiração do aboslute. O que eu quero é uma janela deslizante simples com remoção automática quando o item não for acessado em x
minutos. Eu esperaria que um temporizador interno lidasse com isso. Ele não precisa ser executado a cada segundo por motivos de desempenho; uma vez por minuto é suficiente para mim.
Também não vejo nenhuma configuração sobre como verificar o despejo.
EDIT
Ao adicionar o MemoryCache para DI, existe de fato uma opção paraExpirationScanFrequency
services.AddMemoryCache(options => {
// Check for expired cache items once a minute
options.ExpirationScanFrequency = TimeSpan.FromMinutes(1);
});
mas isso não parece funcionar. Meu retorno de chamada ainda não está sendo invocado vários minutos depois, mesmo que nada o acesse. X está definido como 1
por enquanto.
Essa não é uma afirmação totalmente correta. Conforme explicado no link de uma das respostas, qualquer atividade no cache pode causar o despejo, por exemplo adicionar um novo item ao cache, ou até mesmo ler outra chave:
Veja os usos do
StartScanForExpiredItemsIfNeeded
no código-fonte - ele é chamado em vários métodos comoRemove
, e .SetEntry
TryGetValue
EntryExpired
Por exemplo, você pode brincar com o seguinte:
Não há muito que você possa fazer aqui, exceto alguma abordagem hacky como:
MemoryCache.Compact
manualmente (ou seja, algo como(cache as MemoryCache)?.Compact(0.01)
) quando ela expirarAbaixo está um exemplo de código que inicia um cronômetro para verificar itens expirados, o que pode atender às suas necessidades.
Os itens expirarão do cache a cada 5 segundos - você pode alterar o período alterando as duas linhas:
No exemplo, um cache de memória é criado e três itens são adicionados, cada um dos quais expirará se não for acessado dentro do intervalo de expiração deslizante: