asp.net缓存多线程锁webparts

发布于 2024-11-14 17:44:20 字数 804 浏览 5 评论 0原文

我有以下场景:

假设我们有两个不同的 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
       }
    }

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

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

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

I have following scenario:

Lets say we have two different webparts operating on the same data - one is a pie chart, another is a data table.
in their Page_Load they asynchronously load data from the database and when loaded place it in application cache for further use or use by other web parts. So each o the web parts has code similar to this:

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
       }
    }

Since both webparts operate on the same data it does not make sense for me to execute the code twice.

What is the best approach to have one web part communicate to the other "i am already fetching data so just wait until i place it in cache"?

I have been considering mutex, lock, assigning temporary value to the cache item and waiting until that temporary value changes... many options - which one should I use.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

绿光 2024-11-21 17:44:20

您将需要利用 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;
    }
  }
}

You will want to take advantage of the lock keyword to make sure that the data is loaded and added to the cache in an atomic manner.

Update:

I modified the example to hold the lock accessing Cache for as short as possible. Instead of storing the data directly in the cache a proxy will be stored instead. The proxy will be created and added to the cache in an atomic manner. The proxy will then use its own locking to make sure that the data is only loaded once.

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;
    }
  }
}
残龙傲雪 2024-11-21 17:44:20

为什么不加载数据并将其放入 Global.asax 中的 Application_Start 中的缓存中,那么就不需要锁定了,因为锁定 Cache 是一件严肃的事情。

Why don't you load the data and put it in the cache in the Application_Start in Global.asax, then no lock will be needed since locking Cache is a serious thing.

夏九 2024-11-21 17:44:20

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

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

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

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

You could use a mutex around the test Cache["key"]==null:

The first thread acquires the lock, tests and sees that there's nothing in the cache and goes off to fetch the data. The second thread has to wait for the first to release the mutex. Once the second thread gets in the mutex, it tests, sees the data is there and then continues.

But this would lock up the thread that is running the Page_Load() method - probably a bad thing.

Perhaps a better solution would be to also test if the PageAsyncTask to fetch the data has been started? If not, start it. If so, you shouldn't start another so you may want to register your own event handler to catch when it completes...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文