Asp.Net - Может ли абсолютное истечение срока действия кэша с CacheUpdateCallback быть менее 20 секунд? - PullRequest
4 голосов
/ 20 января 2010

У меня есть тестовый жгут, описанный ниже. Это имеет две метки на странице, которые устанавливаются в пределах page_load, который срабатывает каждую секунду из-за панели обновления и таймера.

Для Label1 установлено значение даты и времени, которое хранится в кэше. Метка 2 установлена ​​на текущую дату и время.

Кэш настроен с абсолютным истечением 5 секунд, и в кеше есть обратный вызов для обновления, чтобы переустановить дату и сделать его действительным еще 5 секунд.

У меня проблема в том, что я вижу обновление кэша каждые 20 секунд, а не каждые 5 секунд, как я ожидал. Если я установлю время на 30 секунд, оно будет обновляться каждые 40 секунд.

Это указывает на то, что срок действия кэша истекает каждые 20 секунд. Кто-нибудь знает способ сократить это время? Если я просто вставлю в кеш с истечением 5 секунд и без обратного вызова, то он будет работать, как я и ожидал, и удаляется каждые 5 секунд.

ASPX:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="CacheTest.aspx.cs" Inherits="CacheTest" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Cache Test</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="ScriptManager1" runat="server" />
        <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
                <asp:Label ID="Label1" runat="server" Text="" />
                <br />
                <asp:Label ID="Label2" runat="server" Text="" />
                <asp:Timer ID="Timer1" Interval="1000" runat="server" />
            </ContentTemplate>
        </asp:UpdatePanel>
    </div>
    </form>
</body>
</html>

Код:

using System;
using System.Web;
using System.Web.Caching;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class CacheTest : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        DateTime CachedDateTime = (DateTime)(Cache["DateTime"] ?? DateTime.MinValue);
        if (CachedDateTime == DateTime.MinValue)
        {
            CachedDateTime = System.DateTime.Now;
            Cache.Insert("DateTime", CachedDateTime, null, DateTime.Now.AddSeconds(5), Cache.NoSlidingExpiration, CacheDateTimeUpdateCallback);
        }
        Label1.Text = CachedDateTime.ToString();
        Label2.Text = DateTime.Now.ToString();
    }

    private void CacheDateTimeUpdateCallback(string key, CacheItemUpdateReason cacheItemUpdateReason, out object value, out CacheDependency dependencies, out DateTime absoluteExipriation, out TimeSpan slidingExpiration)
    {
        value = System.DateTime.Now;
        dependencies = null;
        absoluteExipriation = DateTime.Now.AddSeconds(5);
        slidingExpiration = Cache.NoSlidingExpiration;
    }
}

1 Ответ

2 голосов
/ 20 января 2010

Одна проблема с кодом, который вы разместили, заключается в том, что вы помещаете DateTime в кеш в методе обратного вызова, но проверяете Nullable<DateTime> в Page_Load.

Сказав это, это не проблема. После быстрого просмотра Reflector это выглядит как изюминка реализации Cache: когда вы используете обратный вызов, он вызывается из таймера, который запускается каждые 20 секунд.

Я бы предположил, что причина в повторном входе. Ничто не мешает вам получить доступ к кешу из вашего метода обратного вызова. И делать это, когда он пытается удалить элемент, может быть небезопасно (например, если вы пытаетесь получить доступ к элементу кэша, который находится в процессе удаления, потенциально существует бесконечный цикл).

Поэтому, когда у вас есть обратный вызов, реализация откладывает удаление вашего элемента кэша до тех пор, пока не будет запущен таймер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...