Are private member variables really thread safe in asp.net code behind the class?

I see a random exception "The collection has been modified, the enumeration cannot be executed" - InvalidOperationException.

The exception points to the foreach line in the code snippet below, I know that this happens when the collection changes when enumerated.

However, in my scenario, I see no real chance of this - a UNLESS private member is not thread safe .. Maybe I'm wrong, but that's when I need help to understand and understand .

This is what my code looks like

I have code behind a class that has a private collection, like

private Dictionary<string, string> _someDictionary = SomeConstantClass.ConstantValue; 

In the page prerender completion event, I list the dictionary

 protected override void OnPagePreRenderComplete(object sender, EventArgs e){ _someDictionary["AnotherKey"] = "Another value"; foreach(var dataValuePair in _SomeDictionary){ //Do some operation } } 

I also have a public property that can modify this collection, but it is set in the ascx file, for example

 <tc: UserControlA runat="server" id="abc" CustomProperty="true" /> 

and here is its implementation,

 public bool CustomProperty{ set{ if (value) _someDictionary["CustomProperty"] = "Custom Value"; } } 

This has certainly changed my collection of member variables. But, as I understand it, this property must be started and executed in the Management Initiative itself.

So, I still do not see a scenario in which the collection changes during the pre render complete event.

Any idea what might throw an exception?

other notes: there are many update panels on the page, although this specific user control does nothing interesting and does not even have a postback script. From the log, I see that the problem occurs in the HTTP GET request to the page.

Moreover: suggest me a way (if any) to reproduce this.

For my friends who were interested to know SomeConstantClass.ConstantValue, here it is

 class SomeConstantClass{ public static Dictionary<string, string> ConstantValue = new Dictionary<string, string> { {"ABCD", "EFGH"}, {"HIJK", "LMNO"} }; } 
+4
source share
2 answers

If you return the same instance from SomeConstantClass.ConstantValue , then on several pages there will be a private member variable pointing to the same object. This will cause the object to change when initializing one page when repeating it on the OnPagePreRenderComplete another page.

Make sure you return a new instance of the dictionary each time you access SomeConstantClass.ConstantValue . Example:

 public static Dictionary<string, string> ConstantValue { get { return new Dictionary<string, string> { {"ABCD", "EFGH"}, {"HIJK", "LMNO"} }; } } 

Thus, each page will have its own dictionary object for work. This is a quick solution, you can reorganize the logic so that you do not need to create a new dictionary for each page.

In general, private member variables are only thread safe if they refer to an object that is private to this page and no one else knows about this object or the object itself is not designed for streaming protection. Encapsulating access to a static object that does not depend on a thread through a private member will not make it thread safe.

+7
source

As long as you know that you are not using the dictionary for queries (or you intentionally do this), you can skip the attempt to find out why, and just use the Parallel Dictionary , which is thread safe. Just because the dictionary is closed, it does not make it thread safe.

+2
source

Source: https://habr.com/ru/post/1380411/


All Articles