私は自分のサービスとその SQL データベースの間で対話するために書いているマルチ スレッド サービス用に、もう少し効率的な接続プールを構築しています。基本的に要約すると、クラスに次のコードがあります。
Public Class DBMC
Private Connections As New ArrayList
Private Function GetConnection() As Object
Dim conCounter As Integer = 0
While True
If Connections.Count > conCounter Then
If System.Threading.Monitor.TryEnter(Connections(conCounter), 10) Then
Return Connections(conCounter)
Else
conCounter += 1
End If
ElseIf conCounter > 98 Then
'keep looping until an open connection is found
conCounter = 0
ElseIf conCounter < 98 Then
Dim connection As Object = NewCon()
If connection Is Nothing Then
conCounter = 0
Else
Connections.Add(connection)
Return connection
End If
End If
End While
'below line should never run
Return Nothing
End Function
Public Function DBSelect(ByVal SQL As String) As DataSet
Dim connection As Object = GetConnection()
SyncLock (connection)
'Run the select vs database and do a bunch of other stuff
End SyncLock
Try
System.Threading.Monitor.Exit(connection)
Catch ex As Exception
End Try
Return DataSet
End Function
End Class
したがって、このコードは非常にうまく機能します。異なるスレッドで 500 の select ステートメントをコンピューターが実行できる速さで実行でき、8 つの異なる接続を開きます (おそらくコンピューターの速度が原因で、遅い PC はより多く開く可能性があります)。問題は、DBSelect 関数で、Try/Catch で囲まれた行でモニターの Enter を解放することです。同期クロックを終了すると、オブジェクトのロックがドロップされることがあるため (この場合、行は不要で例外がスローされることがあります)オブジェクトはまだロックされており、その行を実行しなくても永続的にロックされたままになります (この場合、オブジェクトはそれを使用して正常に通過します)。なぜそれを解放するのか、時には解放しないのか、一生わからない. 何か案は?