locked
Condition false, but code inside the if statement executed RRS feed

  • Question

  • I have the following method:

    public bool ConnectAsync()
    {
        if (IsConnected)
            throw new InvalidOperationException("Socket is already connected");
    
        if (IsConnecting)
        {
            throw new InvalidOperationException("Attempt to connect in progress");
        }
    
        . . .
    }

    Where:

        private readonly object padLock = new object();
    
        private bool isConnecting = false;
    
        public bool IsConnected
        {
            get
            {
                lock (padLock)
                { return socket.Connected; }
            }
        }
    
        public bool IsConnecting
        {
            get
            {
                lock (padLock)
                { return isConnecting; }
            }
    
            private set
            {
                lock (padLock)
                { isConnecting = value; }
            }
        }

    enter image description here

    Why the code inside the if statement is executed if my variable isConnecting is false?

    Edit:
    If I use the filed isConnecting instead of the property IsConnecting I have the same behavior. The code runs in the same thread anywhere.

    Edit 2:

    Finally this works:

    lock (padLock)
    {
        if (IsConnecting)
            throw new InvalidOperationException("Attempt to connect in progress");
    }

    And this works:

    {
        if (IsConnecting)
            throw new InvalidOperationException("Attempt to connect in progress");
    }

    But why?


    • Edited by doh666 Friday, November 2, 2012 9:22 PM
    Friday, November 2, 2012 9:17 PM

Answers

  • I'm going to guess that the reason why you saw the value in the debugger to be false, but the executing code saw true, would be due to timing issues around the lock statement. When the executing thread acquired the lock and returned the value for isConnecting, it returned true. But when the debugger thread was able to acquire the lock the value for isConnecting was false.

    • Proposed as answer by Mike Feng Thursday, November 8, 2012 6:16 AM
    • Marked as answer by doh666 Thursday, November 8, 2012 9:16 AM
    Friday, November 2, 2012 9:42 PM

All replies

  • I'm going to guess that the reason why you saw the value in the debugger to be false, but the executing code saw true, would be due to timing issues around the lock statement. When the executing thread acquired the lock and returned the value for isConnecting, it returned true. But when the debugger thread was able to acquire the lock the value for isConnecting was false.

    • Proposed as answer by Mike Feng Thursday, November 8, 2012 6:16 AM
    • Marked as answer by doh666 Thursday, November 8, 2012 9:16 AM
    Friday, November 2, 2012 9:42 PM
  • The possibility is -

    1. Thread A acquired lock
    2. reads IsConnecting as true
    3. Releases the lock
    4. Enters the if(IsConnecting) in ConnectAsync

    After Step3 but before Step4, another thread might opened the connection. So, when step 4 executes, IsConnecting is now 'True'.

    So, putting entire read operation in lock ensures that the IsConnecting value is not changed by any other thread.

    I hope this helps.


    Please mark this post as answer if it solved your problem. Happy Programming!

    • Proposed as answer by Mike Feng Thursday, November 8, 2012 6:16 AM
    Monday, November 5, 2012 5:27 AM