2011-06-17 50 views
3

這段代碼有什麼問題?這段代碼爲什麼總是得到SynchronizationLockException?

我總是在

System.Threading.Monitor.Exit(m_sqlConnection) 

一個

Object synchronization method was called from an unsynchronized block of code

異常,但......不要緊,我是否把顯示器語句中或在try-catch-finally程序塊外,在任何組合中,我總是會得到這個例外。

也就是我編譯完代碼之後。 如果我讓它獲得第一異常後再次運行,它工作得很好...... 反編譯後始終是......

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 

回答

6

你打電話TryEnter,但忽略結果 - 所以即使你不擁有它,你也會嘗試退出顯示器。如果TryEnter返回false,則應採取適當的措施,例如退出該方法。

+0

嗯,換句話說,TryEnter在超時後不會拋出。該死......但發現錯誤:我鎖定在OpenSQLConnection上,但從未解鎖。 – 2011-06-17 07:26:38

+2

@Quandary:不,它會返回一個值。總是檢查文檔:)無論哪種方式,你的代碼都被破壞 - 你仍然會打到finally塊並嘗試關閉連接,然後退出鎖定。 (實際上,如果你還沒有獲得鎖,關閉連接將會非常糟糕 - 你可能正在關閉其他人正在使用的連接...) – 2011-06-17 08:13:52

1

由於lock statementMonitor.EnterMonitor.Exit一個快捷方式,我建議你使用簡單的lock聲明並忽略Monitor類。

+4

由於鎖定語句沒有timout(如果我錯了,這是非常高的),如TryEnter,我會建議您使用TryEnter而不是鎖定。 – 2011-06-17 18:22:26