【重新提问】请教一个有关CacheDependency文件更改后无法正常更新Cache数据的问题,比较怪异

uno 2007-02-01 09:28:51
重新提问的原因是前一帖内的症状描述有误

症状是:
调试的时候若在回调函数内设置断点,则一切正常——在其他窗体内访问CacheManager.ConfigData可以取得正确的内容,当cache.config文件被更改后,刷新窗体能够得到修改后的内容
调试时若无断点、或直接运行访问的时候就出问题——在其他窗体内访问CacheManager.ConfigData可以取得正确的内容,当cache.config文件被更改后,刷新窗体CacheManager.ConfigData返回总是null。因为没有断点,我还无法确定回调函数是否被正常调用……

何解?

附上源码:
****************************************************************

public class CacheManager
{
  private const string CONFIGFILE_DEFAULTNAME = "cache.config";

  private static string _Key = "_CacheConfig";
  private static HttpContext _Context = null;

  public static CacheConfigData ConfigData
  {
    get
    {
      try
      {
        return (CacheConfigData)_Context.Cache[_Key];
      }
      catch
      {
        return null;
      }
    }
  }

  /// <summary>
  /// 初始化
  /// </summary>
  /// <param name="context">应用程序Context对象</param>
  public static void Init(HttpContext context)
  {
    if (null == context) return;
    _Context = context;

    // 获取配置文件路径(默认的配置文件名)
    string configFilePath = context.Server.MapPath(Path.Combine("~/", CONFIGFILE_DEFAULTNAME));

    CacheConfigData dataCacheConfig = GetConfigData(configFilePath);
    if (null == dataCacheConfig) return;

    InitCache(dataCacheConfig); // 实现中...

    // 将配置数据加入缓存
    AddConfigToCache(_Key, dataCacheConfig, configFilePath);

  }

  /// <summary>
  /// 获取配置数据
  /// </summary>
  /// <param name="configFilePath">配置文件路径</param>
  /// <returns>配置数据</returns>
  protected static CacheConfigData GetConfigData(string configFilePath)
  {
    // 如文件不存在则返回
    if (!File.Exists(configFilePath)) return null;

    // 创建配置数据集对象
    CacheConfigData dataCacheConfig = new CacheConfigData();
    try
    {
      // 读取配置文件中的数据到数据集
      dataCacheConfig.ReadXml(configFilePath);
    }
    catch
    {
    }

    // 如果没有数据被读入则返回
    if (!dataCacheConfig.HasChanges()) return null;

    return dataCacheConfig;
  }

  /// <summary>
  /// 将配置数据加入系统缓存
  /// </summary>
  /// <param name="key">键值</param>
  /// <param name="data">数据</param>
  /// <param name="fileDependency">依赖的配置文件</param>
  protected static void AddConfigToCache(string key, CacheConfigData data, string fileDependency)
  {
    if (_Context == null) return;

    // 创建缓存依赖(关联依赖的配置文件)
    CacheDependency dependency = new CacheDependency(fileDependency);

    // 创建缓存更改时的回调函数
    System.Web.Caching.CacheItemRemovedCallback callback = new CacheItemRemovedCallback(CacheManager_CacheItemRemovedCallback);

    // 将配置数据加入系统缓存(不过期)
    _Context.Cache.Add(_Key, data, dependency,
      System.Web.Caching.Cache.NoAbsoluteExpiration,
      System.Web.Caching.Cache.NoSlidingExpiration,
      System.Web.Caching.CacheItemPriority.Default,
      callback);
  }

  /// <summary>
  /// 缓存更改时的回调函数
  /// </summary>
  /// <param name="key"></param>
  /// <param name="data"></param>
  /// <param name="reason"></param>
  protected static void CacheManager_CacheItemRemovedCallback(string key, object data, System.Web.Caching.CacheItemRemovedReason reason)
  {
    if (!(data is CacheConfigData)) return;

    if (reason == System.Web.Caching.CacheItemRemovedReason.DependencyChanged)
    {
      Init(_Context);
    }
  }

  // ...
}
...全文
319 13 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
nyzfl 2007-02-02
  • 打赏
  • 举报
回复
学习

------------------------
http://fenglin.xland.cn
------------------------
uno 2007-02-01
  • 打赏
  • 举报
回复
问题的根源找到了~!@#$%^&*

换了n种方式——
>>DataSet直接读取文件
>>DataSet读文件,再Copy到另一个DataSet,原DataSet设为null
>>用FileStream打开文件,DataSet读取FileStream,关闭FileStream
>>用FileStream打开文件,复制到MemoryStream,关闭FileStream,DataSet读取MemoryStream,关闭MemoryStream

……
都会在文件打开时报错——该文件无法访问,另一个进程正在使用……

初步估计是重新读取文件的时机不好——目前是在回调函数里重新读文件,可能此时依赖文件还没有被正在修改它的编辑器释放
as13019625389 2007-02-01
  • 打赏
  • 举报
回复
这种逻辑问题 只能自己解决,大家只能给你提些意见呵呵
as13019625389 2007-02-01
  • 打赏
  • 举报
回复
只能帮顶了
uno 2007-02-01
  • 打赏
  • 举报
回复
好的
今天晚上再试试,先谢了
cpp2017 2007-02-01
  • 打赏
  • 举报
回复
不是,因为根据现象,调试与运行就是因为权限有差异,所以才让你用身份模拟测试一下. <identity impersonate="true" userName="administrator" password="1111111"/> </system.web>
uno 2007-02-01
  • 打赏
  • 举报
回复
难道访问回调函数需要权限?

身份模拟是“指定asp.net进程的用户”么?
cpp2017 2007-02-01
  • 打赏
  • 举报
回复
令我费解的是,设了断点就正常,不设断点就失效…… ========> 应该是权限的问题. 这样,你先在web.config中用身份模拟,直接运行看看?
uno 2007-02-01
  • 打赏
  • 举报
回复
to 幕白:

我的目的是要让数据在使用之前就被缓存

在InitCache方法中会根据配置数据中的记录逐一反射并调用实现某个接口(一个提供缓存初始化服务方法原型的接口)类的方法

如果在实际使用Data时才加载缓存,这样就失去意义了

令我费解的是,设了断点就正常,不设断点就失效……
confei 2007-02-01
  • 打赏
  • 举报
回复
路过学习
cpp2017 2007-02-01
  • 打赏
  • 举报
回复
而且根据业务逻辑,文件更改意味着配置项的内容更改,我的考虑是与其逐条检测更改,不如重新读取数据整体更新 =========> 这个没有问题,我也不是让你逐条更改. 我的做法: 这个依赖文件可以不用. 也不用初始化. 提供一个方法 GetData() { //如果cahce中没有数据,从数据库中取,并添加到cahce返回. //如果有直接从cache中取. } 如果要更新缓存 updateData() { //直接清空cache,而不用更新依赖文件. //此时cahce中没有数据,直到下一次用户使用GetData才会去数据库中重新查询一次. }
hertcloud 2007-02-01
  • 打赏
  • 举报
回复
要不你在 每一行 关键 代码处

都 写出 一些信息 到一个如log.txt中
看 到那里 有错的
cpp2017 2007-02-01
  • 打赏
  • 举报
回复
因为没有断点,我还无法确定回调函数是否被正常调用…… ========> 你可加点调试信息,比如.在session中加点东西,在其他地方显示出来.

62,244

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧