actually what I'm simply trying to achieve is to get to know multithreading in C#.
SO i have this class called WeakeningEvictionary{TKey, TValue}, which has a private Dictionary{TKey, CachedValue{TValue}} that functions as the cache. CachedValue is a Wrapper that has a Strong- and WeakReference to TValue. After a predefined Time a Task is created to nullify the StrongReference and put it into WeakReference. I also have a HashSet implemented that keeps track of which keyValuePairs to evict. (added to when weakening happened, removed from when SetValue is called) Immediately after GC has done its Job another Task is created to evict all those mentioned Pairs.
Actually I wouldn't need a RecursiveLock for this, but I encountered Issues, when some stored Information is asked recursively because a construction series required so.
So I came up with this code: (Updated, was a not-going-to-work ExtensionMethod before)
public void RecursiveEnter(Action action)
{
if (_spinLock.IsHeldByCurrentThread)
{
action();
}
else
{
bool gotLock = false;
_spinLock.Enter(ref gotLock);//blocking until acquired
action();
if (gotLock) _spinLock.Exit();
}
}
So what I'm trying to do now is:
private void Evict()
{
RecursiveEnter(() =>
{
foreach (TKey key in toEvict)
{
_dict.Remove(key);
}
}
);
}
Alright what if I use
And my Question is: What are the Risks? And are Closures known to cause Issues when being used by Threads in this way?
Thanks for your Input ;-)
Right off the bat, the method call is 100% not going to work: SpinLock is a value type, you must pass it by reference (RecursiveEnter(ref SpinLock spinLock, Action action)) and not by value.
See for example https://learn.microsoft.com/en-us/dotnet/api/system.threading.spinlock?view=netframework-4.7.2#remarks
I'm not sure this is the best thing for you to use: you should start with a higher-level primitive (maybe a ReaderWriterLockSlim) and refine things only with careful testing and understanding.
Related
This is a very strange problem that I have spent the day trying to track down. I am not sure if this is a bug, but it would be great to get some perspective and thoughts on why this is happening.
I am using xUnit (2.0) to run my unit tests. The beauty of xUnit is that it automatically runs tests in parallel for you. The problem that I have found, however, is that Constructor.GetParameters appears to not be thread-safe when the ConstructorInfo is marked as being a thread-safe type. That is, if two threads reach Constructor.GetParameters at the same time, two results are produced, and subsequent calls to this method returns the second result that was created (regardless of the thread that calls it).
I have created some code to demonstrate this unexpected behavior (I also have it hosted on GitHub if you would like to download and try the project locally).
Here is the code:
public class OneClass
{
readonly ITestOutputHelper output;
public OneClass( ITestOutputHelper output )
{
this.output = output;
}
[Fact]
public void OutputHashCode()
{
Support.Add( typeof(SampleObject).GetTypeInfo() );
output.WriteLine( "Initialized:" );
Support.Output( output );
Support.Add( typeof(SampleObject).GetTypeInfo() );
output.WriteLine( "After Initialized:" );
Support.Output( output );
}
}
public class AnotherClass
{
readonly ITestOutputHelper output;
public AnotherClass( ITestOutputHelper output )
{
this.output = output;
}
[Fact]
public void OutputHashCode()
{
Support.Add( typeof(SampleObject).GetTypeInfo() );
output.WriteLine( "Initialized:" );
Support.Output( output );
Support.Add( typeof(SampleObject).GetTypeInfo() );
output.WriteLine( "After Initialized:" );
Support.Output( output );
}
}
public static class Support
{
readonly static ICollection<int> Numbers = new List<int>();
public static void Add( TypeInfo info )
{
var code = info.DeclaredConstructors.Single().GetParameters().Single().GetHashCode();
Numbers.Add( code );
}
public static void Output( ITestOutputHelper output )
{
foreach ( var number in Numbers.ToArray() )
{
output.WriteLine( number.ToString() );
}
}
}
public class SampleObject
{
public SampleObject( object parameter ) {}
}
The two test classes ensure that two threads are created and run in parallel. Upon running these tests, you should get results that look like the following:
Initialized:
39053774 <---- Different!
45653674
After Initialized:
39053774 <---- Different!
45653674
45653674
45653674
(NOTE: I've added "<---- Different!" to denote the unexpected value. You will not see this in the test results.)
As you can see, the result from the very first call to the GetParameters returns a different value than all subsequent calls.
I have had my nose in .NET for quite a while now, but have never seen anything quite like this. Is this expected behavior? Is there a preferred/known way of initializing the .NET type system so that this does not happen?
Finally, if anyone is interested, I ran into this problem while using xUnit with MEF 2, where a ParameterInfo being used as a key in a dictionary is not returning as equal to the ParameterInfo being passed in from a previously saved value. This, of course, results in unexpected behavior and resulting in failed tests when run concurrently.
EDIT: After some good feedback from the answers, I have (hopefully) clarified this question and scenario. The core of the issue is "Thread-Safety" of a "Thead-Safe" type, and acquiring better knowledge of what exactly this means.
ANSWER: This issue ended up being being due to several factors, one of which is due to me never-ending ignorance to multi-threaded scenarios, which it seems I am forever learning with no end for the foreseeable future. I am again appreciative of xUnit for being designed in such a way to learn this territory in such an effective manner.
The other issue does appear to be inconsistencies with how the .NET type system initializes. With the TypeInfo/Type, you get the same type/reference/hashcode no matter which thread accesses it however many times. For MemberInfo/MethodInfo/ParameterInfo, this is not the case. Thread access beware.
Finally, it seems I am not the only person with this confusion and this has indeed been recognized as an invalid assumption on a submitted issue to .NET Core's GitHub repository.
So, problem solved, mostly. I would like to send my thanks and appreciation to all involved in dealing with my ignorance in this matter, and helping me learn (what I am finding is) this very complex problem space.
It is one instance on the first call, and then another instance on every subsequent call.
OK, that's fine. A bit weird, but the method is not documented as always returning the same instance every time.
So, one thread will get one version on the first call, and then each thread will get another (unchanging instance on each subsequent call.
Again, weird, but perfectly legal.
Is this expected behavior?
Well, I would not have expected it before your experiment. But after your experiment, yes, I expect that behaviour to continue.
Is there a preferred/known way of initializing the .NET type system so that this does not happen?
Not to my knowledge.
If I am using that first call to store a key then yes, that is a problem.
Then you have evidence that you should stop doing that. If it hurts when you do that, don't do it.
A ParameterInfo reference should always represent the same ParameterInfo reference regardless of the thread it is on or how many times accessed.
That's a moral statement about how the feature should have been designed. It's not how it was designed, and its clearly not how it was implemented. You can certainly make the argument that the design is bad.
Mr. Lippert is also right in that the documentation does not guarantee/specify this, but this has always been my expectation of and experience with this behavior until this point.
Past performance is no guarantee of future results; your experience was not sufficiently varied until now. Multithreading has a way of confounding people's expectations! A world where memory is constantly changing unless something is keeping it still is contrary to our normal mode of things being the same until something changes them.
As an answer, I am looking at the .NET sources and the ConstructorInfo class has this in its bowels:
private ParameterInfo[] m_parameters = null; // Created lazily when GetParameters() is called.
That's their comment, not mine. Let's see GetParameters:
[System.Security.SecuritySafeCritical] // auto-generated
internal override ParameterInfo[] GetParametersNoCopy()
{
if (m_parameters == null)
m_parameters = RuntimeParameterInfo.GetParameters(this, this, Signature);
return m_parameters;
}
[Pure]
public override ParameterInfo[] GetParameters()
{
ParameterInfo[] parameters = GetParametersNoCopy();
if (parameters.Length == 0)
return parameters;
ParameterInfo[] ret = new ParameterInfo[parameters.Length];
Array.Copy(parameters, ret, parameters.Length);
return ret;
}
So no locking, nothing that would prevent the m_parameters being overridden by a racing thread.
Update: Here is the relevant code inside GetParameters: args[position] = new RuntimeParameterInfo(sig, scope, tkParamDef, position, attr, member); It is clear that in this case RuntimeParameterInfo is just a container for the parameters given in its constructor. There was never even the intention to get the same instance.
That is unlike TypeInfo, which is inheriting from Type and also implementing IReflectableType and which for its GetTypeInfo method just returns itself as an IReflectableType, so maintaining the same instance of the type.
I have a class which manipulates a resource which is shared by multiple threads. The threads pass around control of a mutex in order to manage access to the resource. I would like to manage control of the mutex using the RAII idiom via a disposable object.
There is an additional caveat. When the class begins an operation to manipulate the resource, it is possible that the operation is no longer necessary, or may no longer be performed. This is the result of user action which occurs after the operation has been scheduled to be carried out -- no way around it unfortunately. There are many different operations which might possibly be carried out, and all of them must acquire the mutex in this way. I'm imagining it will look something like this, for example:
public void DoAnOperation()
{
using(RAIIMutex raii = new RAIIMutex(TheMutex))
{
if(ShouldContinueOperation())
{
// Do operation-specific stuff
}
}
}
However, because I'm lazy, I'd like to not have to repeat that if(ShouldContinueOperation()) statement for each operation's function. Is there a way to do this while keeping the // Do operation-specific stuff in the body of the using statement? That seems like the most readable way to write it. For example, I don't want something like this (I'd prefer repeating the if statement if something like this is the only alternative):
public void DoAnOperation()
{
var blaarm = new ObjectThatDoesStuffWithRAIIMutex(TheMutex, ActuallyDoAnOperation);
blaarm.DoAnOperationWithTheMutex();
}
private void ActuallyDoAnOperation()
{
// Do operation-specific stuff
}
It is not entirely clear what ShouldContinueOperation depends on, but assuming that it can be a static function (based on the example code provided in the question), you might like something along the lines of:
public static void TryOperation(Mutex mutex, Action action)
{
using (RAIIMutex raii = new RAIIMutex(mutex))
{
if (ShouldContinueOperation())
action();
}
}
Which you can then use like:
RAIIMutex.TryOperation(TheMutex, () =>
{
// Do operation-specific stuff
});
This combines the using and the ShouldContinueOperation check in one line for the caller. I'm not quite sure about the readability of the lambda syntax used, but that's a matter of personal preference.
To synchronize the access to my properties I use the ReaderWriterLockSlim class. I use the following code to access my properties in a thread-safe way.
public class SomeClass
{
public readonly ReaderWriterLockSlim SyncObj = new ReaderWriterLockSlim();
public string AProperty
{
get
{
if (SyncObj.IsReadLockHeld)
return ComplexGetterMethod();
SyncObj.EnterReadLock();
try
{
return ComplexGetterMethod();
}
finally
{
SyncObj.ExitReadLock();
}
}
set
{
if (SyncObj.IsWriteLockHeld)
ComplexSetterMethod(value);
else
{
SyncObj.EnterWriteLock();
ComplexSetterMethod(value);
SyncObj.ExitWriteLock();
}
}
}
// more properties here ...
private string ComplexGetterMethod()
{
// This method is not thread-safe and reads
// multiple values, calculates stuff, ect.
}
private void ComplexSetterMethod(string newValue)
{
// This method is not thread-safe and reads
// and writes multiple values.
}
}
// =====================================
public static SomeClass AClass = new SomeClass();
public void SomeMultiThreadFunction()
{
...
// access with locking from within the setter
AClass.AProperty = "new value";
...
// locking from outside of the class to increase performance
AClass.SyncObj.EnterWriteLock();
AClass.AProperty = "new value 2";
AClass.AnotherProperty = "...";
...
AClass.SyncObj.ExitWriteLock();
...
}
To avoid unnecessary locks whenever I get or set multiple properties a once I published the ReaderWriterLockSlim-Object and lock it from outside of the class every time I'm about to get or set a bunch of properties. To achieve this my getter and setter methods check if the lock has been acquired using the IsReadLockHeld property and the IsWriteLockHeld property of ReaderWriterLockSlim. This works fine and has increased the performance of my code.
So far so good but when I re-read the documentation about IsReadLockHeld and IsWriteLockHeld I noticed the remark form Microsoft:
This property is intended for use in asserts or for other debugging
purposes. Do not use it to control the flow of program execution.
My question is: Is there a reason why I should not use IsReadLockHeld/IsWriteLockHeld for this purpose? Is there anything wrong with my code? Everything works as expected and much faster than using recursive locks (LockRecursionPolicy.SupportsRecursion).
To clarify this up: This is a minimal example. I don't want to know if the lock itself is necessary or can be removed or achieved in a different way. I just want to know why I should not use IsReadLockHeld/IsWriteLockHeld to control the flow of the programm as stated by the documentation.
After some further research I posted the same question on the German Support Forum of the Microsoft Developer Network and got into discussion with the very helpful moderator Marcel Roma. He was able to contact the programmer of the ReaderWriterLockSlim Joe Duffy who wrote this answer:
I'm afraid my answer may leave something to be desired.
The property works fine and as documented. The guidance really is just
because conditional acquisition and release of locks tends to be buggy
and error-prone in practice, particularly with exceptions thrown into
the mix.
It's typically a good idea to structure your code so that you either
use recursive acquires, or you don't, (and of course the latter is
always easier to reason about); using properties like IsReadLockHeld
lands you somewhere in the middle.
I was one of the primary designers of RWLS and I have to admit it has
way too many bells and whistles. I don't necessarily regret adding
IsReadLockHeld -- as it can come in handy for debugging and assertions
-- however as soon as we added it, Pandora's box was opened, and we RWLS was instantly opened up to this kind of usage.
I'm not surprised that people want to use it as shown in the
StackOverflow thread, and I'm sure there are some legitimate scenarios
where it works better than the alternatives. I merely advise erring on
the side of not using it.
To sum things up: You can use the IsReadLockHeld and the IsWriteLockHeld property to acquire a lock conditionally and everything will work fine, but it is bad programming style and one should avoid it. It is better to stick to recursive or non-recursive locks. To maintain a good coding style IsReadLockHeld and IsWriteLockHeld should only be used for debugging purposes.
I want to thank Marcel Roma and Joe Duffy again for their precious help.
Documentation is advising you the right thing.
Considere the following interleaved execution.
Thread1.AcqrireReadLock();
Thread1.ComplexGetterMethod();
Thread2.ReadIsReaderLockHeldProperty();
Thread1.ReleaseReadLock();
Thread2.ComplexGetterMethod(); // performing read without lock.
The other wrong thing with your code that I see is
SyncObj.EnterReadLock();
try
{
return ComplexGetterMethod();
}
finally
{
SyncObj.ExitReadLock();
}
is not the right way to do things. This is one right:
try
{
SyncObj.EnterReadLock();
return ComplexGetterMethod();
}
finally
{
if (SyncObj.IsReadLockHeld)
SyncObj.ExitReadLock();
}
And this shall be exact definition of your getter method.
I'm very new to multi-threading and for some reason this class is giving me more trouble than it should.
I am setting up a dictionary in the ASP.net cache - It will be frequently queried for individual objects, enumerated occasionally, and written extremely infrequently. I'll note that the dictionary data is almost never changed, I'm planning on letting it expire daily with a callback to rebuild from the database when it leaves the cache.
I believe that the enumeration and access by keys are safe so long as the dictionary isn't being written. I'm thinking a ReaderWriterLockSlim based wrapper class is the way to go but I'm fuzzy on a few points.
If I use Lock I believe that I can either lock on a token or the actual object I'm protecting. I don't see how to do something similar using the ReaderWriter Lock. Am I correct in thinking that multiple instances of my wrapper will not lock properly as the ReaderWriterLocks are out of each other's scope?
What is the best practice for writing a wrapper like this? Building it as a static almost seems redundant as the primary object is being maintained by the cache. Singleton's seem to be frowned upon, and I'm concerned about the above mentioned scoping issues for individual instances.
I've seen a few implementations of similar wrappers around but I haven't been able to answer these questions. I just want to make sure that I have a firm grasp on what I'm doing rather than cutting & pasting my way through. Thank you very much for your help!
**Edit: Hopefully this is a clearer summary of what I'm trying to find out- **
1. Am I correct in thinking that the lock does not affect the underlying data and is scoped like any other variable?
As an example lets say i have the following -
MyWrapperClass
{
ReaderWriterLockSlim lck = new ReaderWriterLockSlim();
Do stuff with this lock on the underlying cached dictionary object...
}
MyWrapperClass wrapA = new MyWrapperClass();
MyWrapperClass wrapB = new MyWrapperClass();
Am I right in thinking that the wrapA lock and wrapB lock won't interact, And that if wrapA & wrapB both attempt operations it will be unsafe?
2. If this is the case what is the best practice way to "share" the lock data?
This is an Asp.net app - there will be multiple pages that need to access the data which is why i'm doing this in the first place. What is the best practice for ensuring that the various wrappers are using the same lock? Should my wrapper be a static or singleton that all threads are using, if not what is the more elegant alternative?
You have multiple dictionary objects in the Cache, and you want each one locked independently. The "best" way is to just use a simple class that does it for you.
public class ReadWriteDictionary<K,V>
{
private readonly Dictionary<K,V> dict = new Dictionary<K,V>();
private readonly ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
public V Get(K key)
{
return ReadLock(() => dict[key]);
}
public void Set(K key, V value)
{
WriteLock(() => dict.Add(key, value));
}
public IEnumerable<KeyValuePair<K, V>> GetPairs()
{
return ReadLock(() => dict.ToList());
}
private V2 ReadLock<V2>(Func<V2> func)
{
rwLock.EnterReadLock();
try
{
return func();
}
finally
{
rwLock.ExitReadLock();
}
}
private void WriteLock(Action action)
{
rwLock.EnterWriteLock();
try
{
action();
}
finally
{
rwLock.ExitWriteLock();
}
}
}
Cache["somekey"] = new ReadWriteDictionary<string,int>();
There is also a more complete example on the help page of ReaderWriterLockSlim on MSDN. It wouldn't be hard to make it generic.
edit To answer your new questions -
1.) You are correct wrapA and wrapB will not interact. They both have their own instance of ReaderWriterLockSlim.
2.) If you need a shared lock amongst all your wrapper classes, then it must be static.
ConcurrentDictionary does everything you want and then some. Part of System.Concurrent.Collections
The standard way to lock is: object lck = new object(); ... lock(lck) { ... } in this instance the object lck represents the lock.
ReadWriterLockSlim isn't much different, its just in this case the actual ReadWriterLockSlim class represents the actual lock, so everywhere you would have used lck you now use your ReadWriterLockSlim.
ReadWriterLockSlim lck = new ReadWriterLockSlim();
...
lck.EnterReadLock();
try
{
...
}
finally
{
lck.ExitReadLock();
}
I am not sure if the title formulates it well so sorry.
I basically have a bunch of elements listing targets for a communication. I placed them in a dictionary though i am open to moving them to a different data structure. My problem is that i have a tree-like structure where a key is a branch and each branch has many leaves. Both the branch and the leaves have names stored in strings (cannot be numeral).
private Dictionary < string, string[]> targets;
For each element in the dictionary i must send a communication, and when the target answers i go to the next target and start over. So after searching i am faced with these dilemmas:
I cannot use the usual foreach because i need to keep the pointer in memory to pass it in between threads.
Since dictionaries are random access it is difficult to keep a pointer
When i receive a communication i must verify if the origins are from a target, so i like the dictionary.contains method for that.
I am fairly new at C#, so the answer is probably obvious but i am finding a hard time finding a data structure that fits my needs. What would be the simplest solution? Can somebody suggest anything?
Thank you.
EDIT
I think my post has confused many, and they are sort of stuck on the terms pointers and threads. By threads i don`t mean that they are parallel, simply that i cannot use a foreach or a loop as the next thread that does the next iteration is triggered by incoming communication. This mechanism cannot be changed at the moment, just the iteration must be. By pointer i wasn't referring to the memory pointers often used in C, i just meant something that points to where you are in a list. Sorry i am a Java programmer so i might be using confusing terms.
I noticed the Enumerator is often inherited and that it can be used with structures such as Dictionary and Linked List. Examples i find talk about this sub structure being encapsulated, and shows foreach loops as examples.
Would it be possible to use GetEnumerator() in some way that the enumerator would remember the current position even when accessed through a different thread?
I am off to test these on my own, but if any input from more experienced people is always appreciated!
I think you need to re-work your architecture a bit, the Dictionary itself is probably not the data structure you need to use for a ordered iteration.
I would consider moving your tree into a linked list instead.
When you kick off your communications I would suggest having your threads callback a delegate to update your list data, or another shared datastructure that keeps track of where you are in the communication process.
static LinkedList<LeafItem> TreeList = new LinkedList<LeafItem>( );
foreach (LeafItem li in TreeList) {
Thread newThread = new Thread(
new ParameterizedThreadStart(Work.DoWork));
newThread.Start(li);
}
You can enumerate over this in parallel using Parallel.ForEach method (from .NET 4). It has been backported as part of the Rx Framework for use in .NET 3.5sp1.
Note - this doesn't actually use one thread per item, but rather partitions the work using the thread pool, based on the hardware thread count of the system on which you're executing (which is usually better...). In .NET 4, it takes advantage of the ThreadPool's new hill climbing and work stealing algorithms, so is very efficient.
this one is a slight long shot, and I suspect I've messed it up somewhere here :/
basically the idea is to create a custom IEnumerator for your dictionary. The idea being that it contains a static variable that keeps the "location" of the enumeration, for continuing.
the following is some skeleton code for something that does work for pausing and restarting.
public class MyDictEnumerator<T> : IEnumerator<T>
{
private List<T> Dict;
private static int curLocation = -1;
public MyDictEnumerator(List<T> dictionary)
{
Dict = dictionary;
}
public T Current
{
get { return Dict[curLocation]; }
}
public void Dispose()
{ }
object System.Collections.IEnumerator.Current
{
get { return Dict[curLocation]; }
}
public bool MoveNext()
{
curLocation++;
if (curLocation >= Dict.Count)
return false;
return true;
}
public void Reset()
{
curLocation = -1;
}
}
Then to use:
MyDictEnumerator<KeyValuePair<string, int>> enumer = new MyDictEnumerator<KeyValuePair<string, int>>(test.ToList());
while (enumer.MoveNext())
{
Console.WriteLine(enumer.Current.Value);
}
I'll admit that this isn't the cleanest way of doing it. But if you break out of the enumerator, and create a new one on another thread, then it will continue at the same point (i think :/)
I hope this helps.
Edit: from your comments:
My alogrithm is more like: Get the
first target Send the message to the
first target Thread DIES - Catch a
port reception event check if its the
right target do some actions - go to
the next target start the loop over.
If you want to process the items asynchronously but not in parallel, you should be able to achieve this by copying the dictionary's keys to a Queue<string> and passing both to the callback that handles your asynchronous responses.
Your completion handler pseduo-code might look like this:
// first extract your dictionary, key, and queue from whatever state
// object you're using to pass data back to the completion event
if (dictionary.Contains(key)) {
// process the response
}
if (queue.Count > 0) {
string key = queue.Dequeue();
string[] messages = dictionary[key];
// send the messages, along with your state data and this callback
}