【问题标题】:asp.net cache multithreading locks webpartsasp.net 缓存多线程锁 webparts
【发布时间】:2011-09-11 21:07:22
【问题描述】:

我有以下场景:

假设我们有两个不同的 Web 部件对相同的数据进行操作 - 一个是饼图,另一个是数据表。 在它们的 Page_Load 中,它们从数据库中异步加载数据,并在加载时将其放入应用程序缓存中以供其他 Web 部件进一步使用或使用。所以每个 web 部件都有类似这样的代码:

protected void Page_Load(object sender, EventArgs e)
    { 
       if (Cache["dtMine" + "_" + Session["UserID"].ToString()]==null)
       {
         ...
         Page.RegisterAsyncTask(new PageAsyncTask(
             new BeginEventHandler(BeginGetByUserID),
             new EndEventHandler(EndGetByUserID), 
             null, args, true));
       }
      else 
       {
         get data from cache and bind to controls of the webpart
       }
    }

由于两个 webpart 都对相同的数据进行操作,因此执行两次代码对我来说没有意义。

让一个 Web 部件与另一个 Web 部件通信的最佳方法是什么?“我已经在获取数据,所以请等到我将其放入缓存中”?

我一直在考虑互斥锁、锁定、为缓存项分配临时值并等待该临时值更改...许多选项 - 我应该使用哪一个。

【问题讨论】:

  • 为什么不做一个静态助手类?

标签: c# asp.net multithreading caching web-parts


【解决方案1】:

您需要利用lock 关键字来确保数据以原子方式加载并添加到缓存中。

更新:

我修改了示例以尽可能短地保持访问Cache 的锁。代替将数据直接存储在缓存中,而是存储代理。代理将以原子方式创建并添加到缓存中。然后代理将使用自己的锁定来确保数据只加载一次。

protected void Page_Load(object sender, EventArgs e)
{ 
   string key = "dtMine" + "_" + Session["UserID"].ToString();

   DataProxy proxy = null;

   lock (Cache)
   {
     proxy = Cache[key];
     if (proxy == null)
     {
       proxy = new DataProxy();
       Cache[key] = proxy;
     }
   }

   object data = proxy.GetData();
}

private class DataProxy
{
  private object data = null;

  public object GetData()
  {
    lock (this)
    {
      if (data == null)
      {
        data = LoadData(); // This is what actually loads the data.
      }
      return data;
    }
  }
}

【讨论】:

  • 我想锁定整个 Cache 对象吗?此外,如果我使用 lock 关键字 - 它是只锁定对象以进行写入还是读取 - 如果所有其他线程需要等待读取其他缓存项而不是我正在更改的缓存项,我担心会降低性能。
  • 是的,您必须锁定对整个 Cache 对象的访问权限。这将序列化所有对Cache 对象的读取和写入。这将对其他线程的读取产生影响。
  • 我修改了代码以缩短锁定时间。
【解决方案2】:

你为什么不把数据加载到Global.asax的Application_Start中的缓存中,那么就不需要锁了,因为锁缓存是件很严重的事情。

【讨论】:

    【解决方案3】:

    您可以在测试周围使用互斥锁Cache["key"]==null

    第一个线程获取锁,测试并看到缓存中没有任何内容,然后开始获取数据。第二个线程必须等待第一个线程释放互斥锁。一旦第二个线程进入互斥体,它就会测试,查看数据,然后继续。

    但是这会锁定运行Page_Load() 方法的线程 - 可能是件坏事。

    也许更好的解决方案是同时测试用于获取数据的PageAsyncTask 是否已启动?如果没有,请启动它。如果是这样,您不应该启动另一个,因此您可能希望注册自己的事件处理程序以在它完成时捕获...

    【讨论】:

      猜你喜欢
      • 2012-12-20
      • 2014-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-24
      • 1970-01-01
      • 2011-04-20
      • 2018-06-20
      相关资源
      最近更新 更多