为什么这段代码总是会出现SynchronizationLockException?

时间:2011-06-17 07:19:08

标签: c# vb.net multithreading locking

这段代码出了什么问题?

我总是得到一个

  

对象同步方法是   从一个不同步的块调用   代码

上的例外情况
System.Threading.Monitor.Exit(m_sqlConnection)

但是......无论我将Monitor语句放在try-catch-finally-block内部还是外部,无论如何组合,我总是得到这个异常。

也就是说,在我编译代码之后。 如果我在获得第一个异常后让它再次运行,它可以正常工作...... 它总是在重新编译后......

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#版本:

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

2 个答案:

答案 0 :(得分:7)

您正在调用TryEnter,但忽略了结果 - 因此即使您不拥有它,您也会尝试退出监视器。如果TryEnter返回false,则应采取适当的操作,例如退出方法。

答案 1 :(得分:0)

由于lock statementMonitor.EnterMonitor.Exit的快捷方式,我建议您简单地使用lock语句并忽略Monitor类。