While using a global integer named GlobalID that I use as a counter,
the following code works fine:
MyFunction(myClass thisClass, Int ID)
{
ListOfMyClass.add(thisClass)
If (thisClass.IsPropertyValueAboveZero)
{
ID = GlobalID;
}
GlobalID++;
Foreach (class someClass in ListOfClasses)
{
MyClass newClass = new MyClass(GlobalID, ID)
MyFunction(newClass, ID) //Recursive Call
}
}
I'm basically using GlobalID as a incrementing counter for each time the function is called. The counter is assigned a starting position for the first time it executes. I'm using a global variable because I wanted to make sure the ID is accurately increased for each pass regardless of execution entering or leaving the recursive call. This function is called (the first time....) from a ForEach loop that assigns the start position of global variable
My goal is to use a Parallel.ForEach for the initial call instead of the regular For Each loop. My problem deals with the counter. I don't know how to manage that counter within multiple threads. If I pass it as a variable to the function, I believe I will have a inaccurate lower / used number leaving the recursive loop. The global variable ensures the next number is higher than the previous number. The thisClass.IsPropertyValueAboveZero is just a arbitrary means of describing action based on a conditional statement. It has no meaningful reference to the rest of the code.
If I have multiple threads that have different starting positions for their counter, how do I accomplish making this thread safe? The only way I see at the moment is manually writing multiple versions of the same function and counter and using TaskFactory
For thread-safe counting, use the Interlocked methods:
System.Threading.Interlocked.Increment(ref globalID)Note: you need to use a field for the
ref. It is possible to expose the field through a property, but can be problematic in code. It is better to use Interlock methods such asInterlocked.CompareExchangeor explicitlockstatements around logic requiring the value in a synchronized manner. The return value forIncrement,Decrement, and so on is usually what should be used inside logic.The recursive call to
MyFunction(newClass, ID)will have the value ofID, but I'm not sure whatIf (thisClass.IsPropertyValueAboveZero)is supposed to do though. Is it to make sure you have a non-zero starting point? If so, it would be better to make sure it is non-zero before the initial call outside of this function.Also the logic in the foreach loop doesn't make sense to me. In
MyClass newClass = new MyClass(GlobalID, ID)theIDwill be argument value, or ifIsPropertyValueAboveZerois true it will be the current value ofGlobalID. SoIDwill typically be less thanGlobalIDsinceGlobalIDis incremented before theforeachloop. I think you are passingGlobalIDwhen you do not need to.