Stefan Steiger
Stefan Steiger

Reputation: 82186

Why does this code always get a SynchronizationLockException?

What's wrong with this code ?

I always get a

Object synchronization method was called from an unsynchronized block of code

Exception on

System.Threading.Monitor.Exit(m_sqlConnection)

But... It doesn't matter whether I put the Monitor statement inside or outside the try-catch-finally-block, in any combination, I always get this exception.

That is, after I compiled the code. If I let it run again after getting the first exception, it works fine... It's always after recompilation...

Public Shared Function GetDataTable(ByRef strSQL As String, ByRef dt As System.Data.DataTable, Optional ByRef strTableName As String = "ThisTable") As Integer
            Dim daQueryTable As System.Data.SqlClient.SqlDataAdapter = Nothing



            Try
                System.Threading.Monitor.TryEnter(m_sqlConnection, 5000)

                If isDataBaseConnectionOpen() = False Then OpenSQLConnection()


                daQueryTable = New System.Data.SqlClient.SqlDataAdapter(strSQL, m_sqlConnection)
                dt = New System.Data.DataTable(strTableName)

                daQueryTable.Fill(dt)
            Catch ex As Exception
                Log(ex)
                Return -1
            Finally
                m_sqlConnection.Close()
                System.Threading.Monitor.Exit(m_sqlConnection)
                daQueryTable.Dispose()
                daQueryTable = Nothing
            End Try

            Return dt.Rows.Count
        End Function ' GetDataTable

C# version:

public static int GetDataTable(ref string strSQL, ref System.Data.DataTable dt, ref string strTableName = "ThisTable")
{
    System.Data.SqlClient.SqlDataAdapter daQueryTable = null;



    try {
        System.Threading.Monitor.TryEnter(m_sqlConnection, 5000);

        if (isDataBaseConnectionOpen() == false)
            OpenSQLConnection();


        daQueryTable = new System.Data.SqlClient.SqlDataAdapter(strSQL, m_sqlConnection);
        dt = new System.Data.DataTable(strTableName);

        daQueryTable.Fill(dt);
    } catch (Exception ex) {
        Log(ex);
        return -1;
    } finally {
        m_sqlConnection.Close();
        System.Threading.Monitor.Exit(m_sqlConnection);
        daQueryTable.Dispose();
        daQueryTable = null;
    }

    return dt.Rows.Count;
} // GetDataTable

Upvotes: 5

Views: 7961

Answers (2)

Uwe Keim
Uwe Keim

Reputation: 40736

Since the lock statement is a shortcut for Monitor.Enter and Monitor.Exit, I would recommend that you simple use the lock statement and ignore the Monitor classes.

Upvotes: -1

Jon Skeet
Jon Skeet

Reputation: 1500805

You're calling TryEnter, but ignoring the result - so you're going to try to exit the monitor even if you don't own it. You should take appropriate action if TryEnter returns false, such as exiting the method.

Upvotes: 10

Related Questions