私有成员变量在类后面的asp.net代码中是否真的是线程安全的?

hum*_*ner 4 .net c# asp.net thread-safety

我看到一个随机异常"集合被修改;枚举可能无法执行" - InvalidOperationException.

例外情况指向下面的代码片段中的foreach行,我知道在枚举时修改集合时会发生这种情况.

但是在我的场景中,我没有看到它真正发生的可能性 - 除非私有成员不是线程安全的......我可能是错的,但这需要我帮助理解和弄清楚.

这是我的代码看起来如何

我有一个类后面的代码,它有一个私有的集合

private Dictionary<string, string> _someDictionary = SomeConstantClass.ConstantValue;
Run Code Online (Sandbox Code Playgroud)

在页面预呈现完成事件中,我正在枚举字典

protected override void OnPagePreRenderComplete(object sender, EventArgs e){
     _someDictionary["AnotherKey"] = "Another value";

     foreach(var dataValuePair in _SomeDictionary){
         //Do some operation
     }
}
Run Code Online (Sandbox Code Playgroud)

我也有一个可以修改这个集合的公共属性,但它在ascx文件中设置如

<tc: UserControlA runat="server" id="abc" CustomProperty="true" />
Run Code Online (Sandbox Code Playgroud)

这是它的实现,

public bool CustomProperty{
    set{
         if (value)
            _someDictionary["CustomProperty"] = "Custom Value";
    }
}
Run Code Online (Sandbox Code Playgroud)

它肯定修改了我的成员变量集合 - 但根据我的理解,这个属性应该在Control Init本身中触发和完成.

所以,我仍然没有看到在预渲染完成事件期间修改集合的场景.

知道什么可能导致异常发生?

其他说明:该页面肯定有许多更新面板,虽然这个特定的用户控件没有做任何花哨的事情,甚至没有回发场景.从日志中我看到问题发生在对页面的HTTP GET请求中.

此外:建议我重现这一点(如果有的话).

对于有兴趣了解SomeConstantClass.ConstantValue的朋友,这里是

class SomeConstantClass{
  public static Dictionary<string, string> ConstantValue = new Dictionary<string, string> {
                      {"ABCD", "EFGH"},
                      {"HIJK", "LMNO"}
                   };
  }
Run Code Online (Sandbox Code Playgroud)

Joã*_*elo 7

如果SomeConstantClass.ConstantValue从那时返回相同的实例,则多个页面将具有指向同一对象的私有成员变量.这将导致在一页的init上更改对象,而在OnPagePreRenderComplete另一页的迭代上进行迭代.

确保在每次访问时返回字典的新实例SomeConstantClass.ConstantValue.例:

public static Dictionary<string, string> ConstantValue
{
    get
    {
        return new Dictionary<string, string>
        {
            {"ABCD", "EFGH"},
            {"HIJK", "LMNO"}
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

这样每个页面都有自己的字典对象可供使用.这是快速解决方案,您可以重构逻辑,这样您就不必为每个页面创建新的字典.

基本上私有成员变量只有线程安全,如果它们引用该页面专用的对象,并且没有其他人知道该对象或该对象本身被设计为线程安全的.通过私有成员封装对非线程安全的静态对象的访问不会使其线程安全.