Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# asp.net缓存多线程锁定Web部件_C#_Asp.net_Multithreading_Caching_Web Parts - Fatal编程技术网

C# asp.net缓存多线程锁定Web部件

C# asp.net缓存多线程锁定Web部件,c#,asp.net,multithreading,caching,web-parts,C#,Asp.net,Multithreading,Caching,Web Parts,我有以下情况: 假设我们有两个不同的Web部件在相同的数据上运行-一个是饼图,另一个是数据表。 在页面加载中,它们异步加载数据库中的数据,并在加载时将其放置在应用程序缓存中,以供其他web部件进一步使用。因此每个web部件都有类似的代码: protected void Page_Load(object sender, EventArgs e) { if (Cache["dtMine" + "_" + Session["UserID"].ToString()]==null)

我有以下情况:

假设我们有两个不同的Web部件在相同的数据上运行-一个是饼图,另一个是数据表。 在页面加载中,它们异步加载数据库中的数据,并在加载时将其放置在应用程序缓存中,以供其他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部件通信的最佳方法是什么“我已经在获取数据,所以请等待,直到我将其放入缓存”


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

您可以在测试
缓存[“key”]==null
周围使用互斥锁:

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

但是这将锁定运行
Page\u Load()方法的线程-可能是一件坏事


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

您将希望利用
lock
关键字来确保以原子方式加载数据并将其添加到缓存中

更新:

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

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

为什么不加载数据并将其放入应用程序\u Start in Global.asax中的缓存中,那么就不需要锁定,因为锁定缓存是一件严肃的事情。

为什么不创建一个静态帮助器类?我想锁定整个缓存对象吗?另外,如果我使用lock关键字(它是只为写而锁定对象还是也为读而锁定对象),那么如果所有其他线程都需要等待读取我正在更改的缓存项以外的其他缓存项,我担心会造成性能损失。是的,您必须锁定对整个
缓存
对象的访问。这将序列化对
缓存
对象的所有读写操作。这将对其他线程的读取产生影响。我修改了代码以在更短的时间内保持锁。