What options do i have to make this code thread safe? - c#

I have this segment of code , a lot of things skipped for brevity but the scene is this one:
public class Billing
{
private List<PrecalculateValue> Values = new List<PrecalculateValue>();
public int GetValue(DateTime date)
{
var preCalculated = Values.SingleOrDefault(g => g.date == date).value;
//if exist in Values, return it
if(preCalculated != null)
{
return preCalculated;
}
// if it does not exist calculate it and store it in Values
int value = GetValueFor(date);
Values.Add(new PrecalculateValue{date = date, value = value});
return value;
}
private object GetValueFor(DateTime date)
{
//some logic here
}
}
I have a List<PrecalculateValue> Values where i store all the values i already calculated for later use, i do these mainly because i don't want to recalculate things twice for the same client, each calculation involve a lot of operations and take between 500 and 1000 ms, and there is a big chance of reuse that value, because of some recursion involved in the hole billing class.
All of these work perfectly until i made a test where i hit two simultaneous calculations for two different clients, and the line Values.Single(g => g.date == date).value returned an exception because it found more than one result in the collection.
So i checked the list and it stored values of both clients in the same list. What can i do to avoid this little problem?

Well, first of all, this line:
return Values.Single(g => g.date == date).value;
makes it so that the subsequent lines will never be called. I'm guessing you've paraphrased your code a little bit here?
If you want to synchronize writes to your Values list, the most straightforward way would be to lock on a common object everywhere in the code that you're modifying the list:
int value = GetValueFor(date);
lock (dedicatedLockObject) {
Values.Add(new PrecalculateValue{date = date, value = value});
}
return value;
But here's something else worth noting: since it looks like you want to have one PrecalculateValue per DateTime, a more appropriate data structure would probably be a Dictionary<DateTime, PrecalculateValue> -- it will provide lightning-fast, O(1) lookup based on your DateTime key, as compared to a List<PrecalculateValue> which would have to iterate to find what you're looking for.
With this change in place, your code might look something like this:
public class Billing
{
private Dictionary<DateTime, PrecalculateValue> Values =
new Dictionary<DateTime, PrecalculateValue>();
private readonly commonLockObject = new object();
public int GetValue(DateTime date)
{
PrecalculateValue cachedCalculation;
// Note: for true thread safety, you need to lock reads as well as
// writes, to ensure that a write happening concurrently with a read
// does not corrupt state.
lock (commonLockObject) {
if (Values.TryGetValue(date, out cachedCalculation))
return cachedCalculation.value;
}
int value = GetValueFor(date);
// Here we need to check if the key exists again, just in case another
// thread added an item since we last checked.
// Also be sure to lock ANYWHERE ELSE you're manipulating
// or reading from the collection.
lock (commonLockObject) {
if (!Values.ContainsKey(date))
Values[date] = new PrecalculateValue{date = date, value = value};
}
return value;
}
private object GetValueFor(DateTime date)
{
//some logic here
}
}
And one last piece of advice: unless it's critical that no more than one of a particular value exist in your collection, the Single method is overkill. If you'd rather just get the first value and disregard potential duplicates, First is both safer (as in, less chance of an exception) and faster (because it doesn't have to iterate over the entire collection).

Could use something like this
public int GetValue(DateTime date)
{
var result = Values.Single(g => g.date == date) ?? GetValueFor(date);
lock (Values)
{
if (!Values.Contains(result)) Values.Add(result);
}
return result.value;
}
private PrecalculateValue GetValueFor(DateTime date)
{
//logic
return new PrecalculateValue() ;
}
Would advise using a dictionary though for a list of key value pairs.

Related

If control in linq query entity framework

,Hi
List<Claimant> list = (from c in CacheManager.ClaimantList.List
where
c.Fullname.Replace("i", "İ").Replace("ı","I").ToUpper().Contains(searchKey.Replace("i", "İ").Replace("ı", "I").ToUpper())
|| c.IdentityNumber.Replace("i", "İ").Replace("ı", "I").ToUpper().Contains(searchKey.Replace("i", "İ").Replace("ı", "I").ToUpper())
|| c.TaxNumber.Replace("i", "İ").Replace("ı", "I").ToUpper().Contains(searchKey.Replace("i", "İ").Replace("ı", "I").ToUpper())
select c).Take(20).ToList<Claimant>();
If Taxnumber is null or "" i get exception because of null data.
My question:
How can i set Taxnumber == 0 , if Taxnumber is null or "" ?
Any help will be appreciated.
Thanks.
You can do:
from c in CacheManager.ClaimantList.List
let taxNumber = c.TaxNumber == null || c.TaxNumber == "" ? "0" : c.TaxNumber
where ...
and then use the taxNumber variable rather than the column.
If you just want certain columns and you don't need the whole Claimant object, you can put something into a select
from c in ClaimantList
where (...)
select new {c.FullName, c.IdentityNumber, TaxNumber = String.IsNullOrEmpty(c.TaxNumber) ? "0" : c.TaxNumber}
You now have an anonymous type with three fields: original FullName, original IdentityNumber and modified TaxNumber.
You could also create a new Claimant for each value by calling its constructor each time:
from c in ClaimantList
where (...)
select new Claimant() {FullName = c.FullName, IdentityNumber = c.IdentityNumber, TaxNumber = String.IsNullOrEmpty(c.TaxNumber) ? "0" : c.TaxNumber}
(I don't know what the constructor of Claimant is like, you might do this slightly differently and set those values in the constructor rather than in the initializer. Or you could write a new constructor.) If the constructor does something non-trivial, it might be wasteful of resources to call it this many times.
In either case, it is stylistically nice to put the conversion (String.IsNullOrEmpty(TaxNumber) ? "0" : TaxNumber or whatever) into its own function somewhere, so that you can change what conversion you do later (see below), and don't have to repeat the code in multiple places.
Another option is that you could use the objects you have, but change the TaxNumber as required. LINQ isn't really the best way of doing this, as you are basically applying side-effects. (LINQ likes to supply a new container with the right data in it, rather than change the data in the original container.) You should really run foreach outside of the Linq code, like this:
List<Claimant> list = from ...
where ...
select ...
foreach (Claimant claimant in list)
{
if (String.IsNullOrEmpty(claimant.TaxNumber))
{ claimant.TaxNumber = "0"; }
}
Ideally you do this after the Take(20) so that you only do it the number of times you need.
Again, putting the conversion in a function will be neater and nicer:
List<Claimant> list = from ...
where ...
select ...
foreach (Claimant claimant in list)
{
claimant.TaxNumber = NormalizeTaxNumber(claimant.TaxNumber); }
}
// ...
public static string NormalizeTaxNumber(string n)
{
return String.IsNullOrEmpty(n) ? "0" : n;
}
However, if you have gone down this route, the next option is to add a method to Claimant which does this change:
List<Claimant> list = from ...
where ...
select ...
foreach (Claimant claimant in list)
{
claimant.NormalizeTaxNumber();
}
public class Claimant
{
// ...
public void NormalizeTaxNumber()
{
if (String.IsNullOrEmpty(TaxNumber))
{ TaxNumber = "0"; }
}
}
and to call this from the foreach loop.
Or, use a different property than TaxNumber:
public class Claimant
{
// ...
public string NormalTaxNumber
{
get { return String.IsNullOrEmpty(TaxNumber) ? "0" : TaxNumber; }
}
}
The advantage of the first strategy is that you only have to call it once - the advantages of the second are that it keeps the original value still available (in the TaxNumber property), and that if you have a bunch of Claimant objects, you don't have to remember whether you have normalized them or not.
You could also use a combination of the two methods: add a new property NormalTaxNumber which converts TaxNumber when needed, and which caches the result so that conversion doesn't have to be done again.
public class Claimant
{
// ...
private string m_normalTaxNumber;
private string ConvertedTaxNumber
{
get { return String.IsNullOrEmpty(TaxNumber) ? "0" : TaxNumber; }
}
public string NormalTaxNumber
{
get
{
if (m_normalTaxNumber == null)
{ m_normalTaxNumber = ConvertedTaxNumber; }
return m_normalTaxNumber;
}
}
}
This only does the calculation once, keeps the original still available, and doesn't require to remember if you've called it before or not. If TaxNumber (the original value) isn't readonly, this is probably more trouble than it's worth as you will have to invalidate the cached value.
If you are never, never going to need to know whether the TaxNumber was originally null, empty or "0", the best advice (and the last strategy) is to convert to the form you want as soon as possible, preferably in the Claimant constructor, if the value of TaxNumber is known there.
If you are getting Claimant objects from a database, you could take this to its logical limit by doing the conversion on the database, either in a stored proc or in a view. If you are using LinqToSql to get the list of Claimant objects, a view could work for you but a stored proc might not.
I have assumed throughout that you want TaxNumber to be available as a string, and that by 0 you mean the string "0". If this isn't the case, and you actually want convert to an int (or similar), some of the strategies above will still work. You can select the converted value as an int in an anonymous type, you can make a new property NormalTaxNumber (with int type), whether cached or not cached, or you can do the conversion upon creation of a Claimant object. Obviously you can't overwrite the string TaxNumber with an int.
If you are parsing the string to an int, things like NormalTaxNumber with caching become more worthwhile, because the conversion from string to int is more costly. (Checking for null or "" is actually very fast, however I thought it valuable to go through some different options anyway.)
Note that almost all of these should still be available to you if you can't modify the Claimant class. You can't write a new constructor, but you can write a factory method which encapsulates exactly the same behavior as a constructor. You can add NormalizeTaxNumber as an extension method, and while you can't add properties, you can add extension methods with no arguments which work almost exactly like properties.
My last observation is that "0" might not necessarily be a better value for missing data than null or "". Either of the latter is more commonly used to indicate missing values, especially null. Perhaps you should choose one of those as the default (and maybe apply one of the above strategies in reverse to enforce it as the only 'N/A' value?) If it's just a question of it looking nice when you print the object out, you could override ToString() to swap in the "0" only when needed.

Does Creating a Variable to hold a cast Save Overhead

When I need to save a big list of my Custom Objects between postbacks on my Asp.Net project, I like to save them in a Session Variable, then Cast them to a List<> in a property
Something like this
public partial class MyPage : Page
{
private List<MyStorageObject> MyList
{
get {return (List<MyStorageObject>) Session["MySessionString"]; }
set { Session["MySessionString"] = value; }
}
}
Then I put a List of my objects in there, and get to call it in a later postback. I think this is a pretty standard way to make objects last longer than the page LifeCycle.
But my question is, when I'm using the List more than once, say I'm going to do a few things with it, I can't help but think every time I access it, it's casting an object to a List<> but if I create a variable it looks like it's avoiding the casting.
private void DoStuffWithMyList()
{
var x = MyList;
//Assuming I'm going to call the list 20 times in my method
x.first(); // Is this any more efficient / cleaner
MyList.first(); // Than this?
//Or do they both get converted into the same thing in the end anyway
}
Yes, in the first case (using x) you're only accessing the property once and then reusing the returned value.
In the second case (using MyList multiple times) you'll be looking the value up in the session every time you use it. It's also casting, but that's likely to be cheaper than the session lookup.
Fundamentally I'd regard the first version as cleaner, as it makes it clearer that you're trying to reuse the same value several times.
Of course avoiding the casting is more efficient.
Why not combine the two?:
private List<MyStorageObject> _MyList = null;
private List<MyStorageObject> MyList
{
get {
if (this._MyList == null)
{
this._MyList = (List<MyStorageObject>)Session["MySessionString"];
}
return this._MyList;
}
set {
this._MyList = value;
Session["MySessionString"] = value;
}
}

List threading issue

I'm trying to make my application thread safe. I hold my hands up and admit I'm new to threading so not sure what way to proceed.
To give a simplified version, my application contains a list.
Most of the application accesses this list and doesn't change it but
may enumerate through it. All this happens on the UI thread.
Thread
one will periodically look for items to be Added and Removed from the
list.
Thread two will enumerate the list and update the items with
extra information. This has to run at the same time as thread one as
can take anything from seconds to hours.
The first question is does anyone have a recommend stragy for this.
Secondly I was trying to make seperate copies of the list that the main application will use, periodically getting a new copy when something is updated/added or removed, but this doesn't seem to be working.
I have my list and a copy......
public class MDGlobalObjects
{
public List<T> mainList= new List<T>();
public List<T> copyList
{
get
{
return new List<T>(mainList);
}
}
}
If I get copyList, modify it, save mainlist, restart my application, load mainlist and look again at copylist then the changes are present. I presume I've done something wrong as copylist seems to still refer to mainlist.
I'm not sure if it makes a difference but everything is accessed through a static instance of the class.
public static MDGlobalObjects CacheObjects = new MDGlobalObjects();
This is the gist using a ConcurrentDictionary:
public class Element
{
public string Key { get; set; }
public string Property { get; set; }
public Element CreateCopy()
{
return new Element
{
Key = this.Key,
Property = this.Property,
};
}
}
var d = new ConcurrentDictionary<string, Element>();
// thread 1
// prune
foreach ( var kv in d )
{
if ( kv.Value.Property == "ToBeRemoved" )
{
Element dummy = null;
d.TryRemove( kv.Key, out dummy );
}
}
// thread 1
// add
Element toBeAdded = new Element();
// set basic properties here
d.TryAdd( toBeAdded.Key, toBeAdded );
// thread 2
// populate element
Element unPopulated = null;
if ( d.TryGetValue( "ToBePopulated", out unPopulated ) )
{
Element nowPopulated = unPopulated.CreateCopy();
nowPopulated.Property = "Populated";
// either
d.TryUpdate( unPopulated.Key, nowPopulated, unPopulated );
// or
d.AddOrUpdate( unPopulated.Key, nowPopulated, ( key, value ) => nowPopulated );
}
// read threads
// enumerate
foreach ( Element element in d.Values )
{
// do something with each element
}
// read threads
// try to get specific element
Element specific = null;
if ( d.TryGetValue( "SpecificKey", out specific ) )
{
// do something with specific element
}
In thread 2, if you can set properties so that the whole object is consistent after each atomic write, then you can skip making a copy and just populate the properties with the object in place in the collection.
There are a few race conditions in this code, but they should be benign in that readers always have a consistent view of the collection.
actly copylist is just a shallow copy of the mainList. the list is new but the refrences of the objects contained in the list are still the same. to achieve what you are trying to you have to make a deep copy of the list
something like this
public static IEnumerable<T> Clone<T>(this IEnumerable<T> collection) where T : ICloneable
{
return collection.Select(item => (T)item.Clone());
}
and use it like
return mainList.Clone();
looking at your ques again.. i would like to suggest an overall change of approach.
you should use ConcurrentDictionary() as you are using .Net 4.0. in that you wont hav eto use locks as a concurrent collection always maintains a valid state.
so your code will look something like this.
Thread 1s code --- <br>
var object = download_the_object();
dic.TryAdd("SomeUniqueKeyOfTheObject",object);
//try add will return false so implement some sort of retry mechanism
Thread 2s code
foreach(var item in Dictionary)
{
var object item.Value;
var extraInfo = downloadExtraInfoforObject(object);
//update object by using Update
dictionary.TryUpdate(object.uniqueKey,"somenewobjectWithExtraInfoAdded",object);
}

What is the best way to store static data in C# that will never change

I have a class that stores data in asp.net c# application that never changes. I really don't want to put this data in the database - I would like it to stay in the application. Here is my way to store data in the application:
public class PostVoteTypeFunctions
{
private List<PostVoteType> postVotes = new List<PostVoteType>();
public PostVoteTypeFunctions()
{
PostVoteType upvote = new PostVoteType();
upvote.ID = 0;
upvote.Name = "UpVote";
upvote.PointValue = PostVotePointValue.UpVote;
postVotes.Add(upvote);
PostVoteType downvote = new PostVoteType();
downvote.ID = 1;
downvote.Name = "DownVote";
downvote.PointValue = PostVotePointValue.DownVote;
postVotes.Add(downvote);
PostVoteType selectanswer = new PostVoteType();
selectanswer.ID = 2;
selectanswer.Name = "SelectAnswer";
selectanswer.PointValue = PostVotePointValue.SelectAnswer;
postVotes.Add(selectanswer);
PostVoteType favorite = new PostVoteType();
favorite.ID = 3;
favorite.Name = "Favorite";
favorite.PointValue = PostVotePointValue.Favorite;
postVotes.Add(favorite);
PostVoteType offensive = new PostVoteType();
offensive.ID = 4;
offensive.Name = "Offensive";
offensive.PointValue = PostVotePointValue.Offensive;
postVotes.Add(offensive);
PostVoteType spam = new PostVoteType();
spam.ID = 0;
spam.Name = "Spam";
spam.PointValue = PostVotePointValue.Spam;
postVotes.Add(spam);
}
}
When the constructor is called the code above is ran. I have some functions that can query the data above too. But is this the best way to store information in asp.net? if not what would you recommend?
This is a candidate for an immutable struct that "looks like" an enumeration:
(Also, I noticed you used the same id value for two of them, so I fixed that...
You can use the following just as you would an enumeration...
PostVoteTypeFunctions myVar = PostVoteTypeFunctions.UpVote;
and real nice thing is that this approach requires no instance storage other than a 4-byte integer (which will be stored on stack, since it's a struct). All hard-coded values are stored in the type itself... of which only one will exist per AppDomain...
public struct PostVoteTypeFunctions
{
private int id;
private bool isDef;
private PostVoteTypeFunctions ( ) { } // private to prevent direct instantiation
private PostVoteTypeFunctions(int value) { id=value; isDef = true; }
public bool HasValue { get { return isDef; } }
public bool isNull{ get { return !isDef; } }
public string Name
{
get
{ return
id==1? "UpVote":
id==2? "DownVote":
id==3? "SelectAnswer":
id==4? "Favorite":
id==5? "Offensive":
id==6? "Spam": "UnSpecified";
}
}
public int PointValue
{
get
{ return // Why not hard code these values here as well ?
id==1? PostVotePointValue.UpVote:
id==2? PostVotePointValue.DownVote
id==3? PostVotePointValue.SelectAnswer:
id==4? PostVotePointValue.Favorite:
id==5? PostVotePointValue.Offensive:
id==6? PostVotePointValue.Spam:
0;
}
}
// Here Add additional property values as property getters
// with appropriate hardcoded return values using above pattern
// following region is the static factories that create your instances,
// .. in a way such that using them appears like using an enumeration
public static PostVoteTypeFunctions UpVote = new PostVoteTypeFunctions(1);
public static PostVoteTypeFunctions DownVote= new PostVoteTypeFunctions(2);
public static PostVoteTypeFunctions SelectAnswer= new PostVoteTypeFunctions(3);
public static PostVoteTypeFunctions Favorite= new PostVoteTypeFunctions(4);
public static PostVoteTypeFunctions Offensive= new PostVoteTypeFunctions(5);
public static PostVoteTypeFunctions Spam= new PostVoteTypeFunctions(0);
}
It is difficult to tell from the fragment of code you have posted whether you expose any of the data outside the class.
If not, then this would work. However, if not, there are several issues:
If you are exposing the List, you should only ever return a copy of it as an IEnumerable<PostVoteType> using the yield keyword.
Make sure your PostVoteType is immutable, otherwise the references can be changed and the fields used might be altered
Looking at your code, it looks like you're just trying to create a set of objects that really just put the enum PostVotePointValue into some sort of list. I.e. you already have what you need defined in just the enum itself. I would encourage you to not define the same information in two places (this data store you are asking for and the enum). This is common mistake I see people make. They create a lookup table/list, then create an enum that mirrors the rows of the table and that means they have to modify two places for any change to the list.
If PostVotePointValue isn't an enum but just some constants or if there is more info you are planning on packing in, then this isn't relevant.
Here's some examples of how to work with Enums as 'lists' from http://www.csharp-station.com/Tutorials/Lesson17.aspx
// iterate through Volume enum by name
public void ListEnumMembersByName()
{
Console.WriteLine("\n---------------------------- ");
Console.WriteLine("Volume Enum Members by Name:");
Console.WriteLine("----------------------------\n");
// get a list of member names from Volume enum,
// figure out the numeric value, and display
foreach (string volume in Enum.GetNames(typeof(Volume)))
{
Console.WriteLine("Volume Member: {0}\n Value: {1}",
volume, (byte)Enum.Parse(typeof(Volume), volume));
}
}
// iterate through Volume enum by value
public void ListEnumMembersByValue()
{
Console.WriteLine("\n----------------------------- ");
Console.WriteLine("Volume Enum Members by Value:");
Console.WriteLine("-----------------------------\n");
// get all values (numeric values) from the Volume
// enum type, figure out member name, and display
foreach (byte val in Enum.GetValues(typeof(Volume)))
{
Console.WriteLine("Volume Value: {0}\n Member: {1}",
val, Enum.GetName(typeof(Volume), val));
}
}
}
You should be able to adapt the above into an approach that will give you a list that you can use for databinding if you need it.
I am wondering why you could not just use a simple enum for this?
public enum PostVoteType
{
UpVote = 0,
DownVote = 1,
SelectAnswer = 2,
Favorite = 3,
Offensize = 4,
Spam = 5
}
"Never" is a very hard word indeed.
In your particular case you are asserting that not only is your PostVoteType data absolute and immutable, but so is the container collection. Frankly I don't believe you can know that, because you are not the business (your interpretation of requirement is imperfect) and you are not psychic (your knowledge of the future is imperfect).
I would suggest that you always store any data which cannot be expressed as an enumeration in some kind of repository. Where you expect relational and/or transactional and/or mutable needs that means a database, if you expect high read to write ratio that can be a config file (which I believe this case should be).
Edit: In terms of memory persistance I agree with others that the cache is the best place to store this, or rather in a domain object which is backed by cache.
Aside: your construction of PostVoteTypes is horrible - strongly suggest you want a refactor :)
If it doesn't change, is commonly accessed, and is the same for all users, then the .NET cache is the proper place. Have a property that yields these values. Inside, the property checks the cache for this list and returns the stored value; otherwise, it constructs it from scratch, adds to the cache, and returns the value.
This should still probably be configured in the database though, even if you cache it. I imagine that you'll need to use these value in conjunction with other data in your DB.
When you need to often access the same data, and need not to store it into the underlying database, and that this data is about the same in every situation the application may encounter, then I suggest to use caching. Caching is born from these requirements. Caching is normally the fastest way to providing data as they are always kept in memory or something similar to ease and to make the access easier by the application.
Here is a nice caching tool provided with Microsoft Enterprise Library, the Caching Application Block.
I think it is worth to take the time to learn how to use it effectively.
create a singleton class.

Updating fields of values in a ConcurrentDictionary

I am trying to update entries in a ConcurrentDictionary something like this:
class Class1
{
public int Counter { get; set; }
}
class Test
{
private ConcurrentDictionary<int, Class1> dict =
new ConcurrentDictionary<int, Class1>();
public void TestIt()
{
foreach (var foo in dict)
{
foo.Value.Counter = foo.Value.Counter + 1; // Simplified example
}
}
}
Essentially I need to iterate over the dictionary and update a field on each Value. I understand from the documentation that I need to avoid using the Value property. Instead I think I need to use TryUpdate except that I don’t want to replace my whole object. Instead, I want to update a field on the object.
After reading this blog entry on the PFX team blog: Perhaps I need to use AddOrUpdate and simply do nothing in the add delegate.
Does anyone have any insight as to how to do this?
I have tens of thousands of objects in the dictionary which I need to update every thirty seconds or so. Creating new ones in order to update the property is probably not feasible. I would need to clone the existing object, update it and replace the one in the dictionary. I’d also need to lock it for the duration of the clone/add cycle. Yuck.
What I’d like to do is iterate over the objects and update the Counter property directly if possible.
My latest research has led me to to Parallel.ForEach which sounds great but it is not supposed to be used for actions that update state.
I also saw mention of Interlocked.Increment which sounds great but I still need to figure out how to use it on each element in my dictionary in a thread safe way.
First, to solve your locking problem:
class Class1
{
// this must be a variable so that we can pass it by ref into Interlocked.Increment.
private int counter;
public int Counter
{
get{return counter; }
}
public void Increment()
{
// this is about as thread safe as you can get.
// From MSDN: Increments a specified variable and stores the result, as an atomic operation.
Interlocked.Increment(ref counter);
// you can return the result of Increment if you want the new value,
//but DO NOT set the counter to the result :[i.e. counter = Interlocked.Increment(ref counter);] This will break the atomicity.
}
}
Iterating the just values should be faster than iterating the key value pair. [Though I think iterating a list of keys and doing the look-ups will be faster still on the ConcurrentDictionary in most situations.]
class Test
{
private ConcurrentDictionary<int, Class1> dictionary = new ConcurrentDictionary<int, Class1>();
public void TestIt()
{
foreach (var foo in dictionary.Values)
{
foo.Increment();
}
}
public void TestItParallel()
{
Parallel.ForEach(dictionary.Values,x=>x.Increment() );
}
}
ConcurrentDictionary doesn't help you with accessing members of stored values concurrently, just with the elements themselves.
If multiple threads call TestIt, you should get a snapshot of the collection and lock the shared resources (which are the individual dictionary values):
foreach (KeyValuePair<int, Class1> kvp in dict.ToArray())
{
Class1 value = kvp.Value;
lock (value)
{
value.Counter = value.Counter + 1;
}
}
However, if you want to update the counter for a specific key, ConcurrentDictionary can help you with atomically adding a new key value pair if the key does not exist:
Class1 value = dict.GetOrAdd(42, key => new Class1());
lock (value)
{
value.Counter = value.Counter + 1;
}
AddOrUpdate and TryUpdate indeed are for cases in which you want to replace the value for a given key in a ConcurrentDictionary. But, as you said, you don't want to change the value, you want to change a property of the value.
You can use the AddOrUpdate function.
Here is how you can increment the current value by 1:
dict.AddOrUpdate(key, 1, (key, oldValue) => oldValue + 1);

Categories