I've learned more about the C# lock statement and equivalent code in C++/CLI compared to my
first article. It turned out my suppositions about using the Monitor class were functional, but using the
this pointer was way off base (as was the code I was porting).
From MSDN: In general, avoid locking on a public type, or instances beyond your code's control. lock (this) is a problem if the instance can be accessed publicly.
So, in general, you should declare a private object in your class,:
e.g.
private System::Object lockThis;
In your class constructor, you need to initialize:
lockThis = gcnew System::Object();In the class' method where you want the lock to occur:
try
{
Monitor::Enter(lockThis);
m_internalCounter++;
}
finally
{
Monitor::Exit(lockThis);
}This code block will only lock the code in the method that calls
Monitor (assuming I've read the documentation correctly.) The reason for the try/finally block is to make sure the
Monitor::Exit call is made.
I made the above changes to my ported code, and then performed some stress testing.
Monitor::Enter will block if the object
lockThis is held by another thread. However, the
m_internalCounter++ executes so quickly that there did not seem to be a problem with 20 objects executing the same method. I generated fake exceptions by causing
int overflows in order to test the try-finally block.
Monitor::Exit was called in every instance.
Like I said in my last
article, I'm no expert on this stuff.