在Page_Load中调用两次乱序的方法

时间:2017-03-10 13:45:50

标签: c# asp.net sharepoint sharepoint-2013 page-lifecycle

我在SharePoint Stack Exchange中问过这个问题,但认为它可能不是特定于SharePoint的问题,可能与.NET页面生命周期有关。可以找到原始问题here

我正在为SharePoint 2013编写一个Web应用程序,并且遇到了一些有趣的行为。基本上,我正在制作一系列网络请求,但首先需要将这些请求存储在Dictionary中以供日后使用。但是,如果我在调试时打开3个选项卡并同时命中它们,我会看到Dictionary对象未清空,并在尝试多次添加同一端点时导致异常。以下是该应用的相关代码:

public partial class TestControl : UserControl
{
    protected static Dictionary<string, string> _endpoints = new Dictionary<string, string>();

    protected void Page_Load(object sender, EventArgs e)
    {
        //clear the lists of endpoints each time the page is loaded
        _endpoints.Clear();
        ...
        MethodThatAddsToDictionary();
       ...
    }

    public static void MethodThatAddsToDictionary()
    {
        ...
        _endpoints.Add(response.First(), response.Last());
    }
}

调试,有时MethodThatAddsToDictionary()_endpoints.Clear()事件的顶部Page_Load运行之前被调用两次,我会得到一个ArgumentException说:< / p>

  

已添加具有相同键的项目

我觉得我错过了关于应用程序生命周期的基本信息,但是到目前为止还没有发现任何有用的信息。在添加它之前,我可以将.Add()包装在条件中以检查密钥,但我觉得这是一个绑定。我错过了什么?

提前致谢!

1 个答案:

答案 0 :(得分:1)

<强> ehhmm ... 如果您不使用静态字典作为一种共享内存缓存,则可以删除示例代码的所有静态关键字。在这种情况下,您也无需调用Clear()方法。

如果您使用static词典作为一种内存缓存(我不建议使用),您可能会遇到多次调用您的页面会导致竞争状况,因为它们可能会被不同的处理线程。为了解决这个问题,你可以使用一个lock语句来强制线程同步对字典的非线程安全调用,如下所示:

public partial class TestControl : UserControl
{
    protected static Dictionary<string, string> _endpoints = 
                                      new Dictionary<string, string>();

    //lock object needs to be static in this case
    private static object _lockObject = new object();

    protected void Page_Load(object sender, EventArgs e)
    {
        lock(_lockObject) //only one thread may pass at the same time,
                          //others will wait.
        {
            //clear the lists of endpoints each time the page is loaded
            _endpoints.Clear();
            ...
            MethodThatAddsToDictionary();

         }
     }

     public static void MethodThatAddsToDictionary()
     {
         ...
         _endpoints.Add(response.First(), response.Last());
     }
 }

请注意;这是一个肮脏的修复程序,它将有效地取消对此特定调用的所有多线程优化web服务器(从而导致性能损失)。