Synchronization exception

  • Thread starter Thread starter David
  • Start date Start date
D

David

I have a block of code:

private CycleStates vCurrentCycleState;//Always use get. Protects the
critical section
public CycleStates CurrentCycleState
{
get
{
CycleStates retval;
System.Threading.Monitor.Enter(vCurrentCycleState);
retval =vCurrentCycleState;
System.Threading.Monitor.Exit(vCurrentCycleState);
return retval;
}
set
{

if (value!=vCurrentCycleState)
{
switch(value)
{
case CycleStates.ActiveState:

System.Threading.Monitor.Enter(vCurrentCycleState);

Activate();
vCurrentCycleState = CycleStates.Welding;
System.Threading.Monitor.Exit(vCurrentCycleState);

break;
case CycleStates.InactiveState:
System.Threading.Monitor.Enter(vCurrentCycleState);

DeActivate();
vCurrentCycleState = CycleStates.InactiveState;
System.Threading.Monitor.Exit(vCurrentCycleState);

break;
}
}
}

The purpose is to make sure that whenever the state changes from active to
inactive, the Activate() or Deactivate() function is called. Also, threads
are checking the current Cycle State, to see if it is active or inactive, so
I want to make sure that all the operations in Activate() or Deactivate() are
completed before returning the value of the test. It seems like a great
appliacation for a Critical Section.


However, when I run it, I get an exception:



"Object synchronization method was called from an unsynchronized block of
code."


What is an "unsynchronized" block of code? I'm confident that you can't hit
the Exit method without having hit the Enter method two lines before, so the
lock owner really should be the thread in question every time. The Help file
says that the thread calling Exit() must be the owner of the lock. Is the
"owner" of the lock the thread that called Enter()? That's what I assume,
but it's obvious that in this case, you can only get to the ExitI() method
after calling the Enter() method, so doesn't that make that thread the owner?
 
Use lock(vCurrentCycleState) { ... } instead. This makes Exit be called
in a finally block. Also note that you are likely changing
vCurrentCycleState inside the protected code that will make the Exit
called on a different object than Enter. By using lock C# complier will
copy the original object and use it for both calls.

I also suggest to create a separate object (private object syncObj = new
object(); is just fine) for synchronization if you don't need to lock on
vCurrentCycleState.

Kornél
 
Thanks. I was unaware that changing the value of vCurrentCycleState would
changed the locked object. That should do it.
 
Back
Top