[英]VB6, ADO, Asynchronous command and closing the connection
確實存在一個快速問題,我是否需要關閉ADO命令? 我在幾個地方讀過,簡單地將其設置為不執行與關閉它具有相同的作用,但是我還沒有找到確切的答案。
我有一個VB6例程,該例程在運行時創建一個連接和命令對象,該對象異步執行一個不返回任何結果的存儲過程。
在此例程結束時,兩個對象均設置為空。 以下代碼准確顯示了執行的操作
' Open connection
con.Open
'
' Create command to execute stored proc
Set cmd = New ADODB.Command
cmd.ActiveConnection = con
cmd.CommandType = adCmdStoredProc
cmd.CommandText = cSQLDelete
cmd.Parameters.Append cmd.CreateParameter _
("@ExpiryDate=", adDate, adParamInput, 20, ExpiryDate)
'
' Run procedure, no results
cmd.Execute , , adExecuteNoRecords + adAsyncExecute
'
' Tidy up
Set cmd = Nothing
Set con = Nothing
注意缺少con.Close。 如果將其插入con = nothing之前,則存儲過程將不會運行-我認為由於它是異步的,因此在關閉連接之前沒有時間執行。
沒有con.Close,這可以正常工作。
因此,我的問題是不關閉連接會有什么影響。 連接會在后台簡單地超時嗎? 請記住,此函數稱為A LOT,到目前為止測試還沒有發現任何問題。
如果在存儲過程完成后需要關閉連接,該怎么辦? 我有C#背景,不熟悉VB6,發現在運行時創建帶有事件的對象是一個尷尬的過程。
PS SQL Server 2008年
謝謝
在斷開連接之前,您必須等待命令完成或失敗。 在執行命令時關閉連接會立即引發錯誤,將連接設置為空不會釋放它所持有的資源,並且可能會使程序崩潰。
正確的方法是在命令完成后關閉連接,通常是通過監視ExecuteComplete事件(您的連接必須屬於類或窗體)來關閉。
您可以使用類似的內容:
Option Explicit
Dim WithEvents con As ADODB.Connection
Dim bExecuting As Boolean
Private Sub cmdCancel_Click()
If Not bExecuting Then Exit Sub
If Not con Is Nothing Then
con.Cancel
End If
bExecuting = False
End Sub
Private Sub cmdExecute_Click()
If bExecuting Then Exit Sub
If con Is Nothing Then
Set con = New ADODB.Connection
con.Open "Provider=..."
End If
bExecuting = True
con.Execute "WAITFOR DELAY '000:00:10'", , adExecuteNoRecords + adAsyncExecute
End Sub
Private Sub cmdExit_Click()
If bExecuting Then Exit Sub
Unload Me
End Sub
Private Sub con_ExecuteComplete(ByVal RecordsAffected As Long, ByVal pError As ADODB.Error, adStatus As ADODB.EventStatusEnum, ByVal pCommand As ADODB.Command, ByVal pRecordset As ADODB.Recordset, ByVal pConnection As ADODB.Connection)
If Not pError Is Nothing Then Debug.Print pError.Description
bExecuting = False
End Sub
Private Sub Form_Load()
bExecuting = False
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
If bExecuting Then Cancel = 1
End Sub
Private Sub Form_Unload()
If Not con Is Nothing Then
If con.State = adStateOpen Then con.Close
set con = Nothing
End If
End Sub
如果連接不忙(State = Open),此代碼將執行命令。 否則,將其放在堆棧上並在當前命令完成時執行它。 我對VB陣列的了解有限,因此感到有點難看-可能有更好的方法來創建FIFO隊列?
Dim WithEvents mobjAdoConn As ADODB.Connection
Dim CommandArray() As String
Private Sub Command1_Click()
Dim cmdNo As Integer
If mobjAdoConn.State <> adStateOpen Then
cmdNo = UBound(CommandArray)
ReDim Preserve CommandArray(cmdNo + 1)
CommandArray(cmdNo) = "WAITFOR DELAY '000:00:10'"
Label2.Caption = cmdNo
Else
mobjAdoConn.Execute "WAITFOR DELAY '000:00:10'", , adExecuteNoRecords + adAsyncExecute
End If
End Sub
Private Sub Form_Load()
On Error GoTo Err
Set mobjAdoConn = New ADODB.Connection
mobjAdoConn.ConnectionTimeout = 30
mobjAdoConn.ConnectionString = "Provider..."
mobjAdoConn.Open
ReDim CommandArray(1)
Exit Sub
Err:
MsgBox Err.Description, vbOKOnly
End Sub
Private Sub mobjAdoConn_ExecuteComplete(ByVal RecordsAffected As Long, ByVal pError As ADODB.Error, adStatus As ADODB.EventStatusEnum, ByVal pCommand As ADODB.Command, ByVal pRecordset As ADODB.Recordset, ByVal pConnection As ADODB.Connection)
Dim cmd As String
Dim i As Integer
Dim cmds As Integer
cmds = UBound(CommandArray)
If cmds > 1 Then
cmd = CommandArray(1)
If cmds = 2 Then
ReDim CommandArray(1)
Label2.Caption = 0
Else
For i = 2 To cmds - 1
CommandArray(i - 1) = CommandArray(i)
Next i
ReDim Preserve CommandArray(cmds - 1)
Label2.Caption = cmds - 2
End If
mobjAdoConn.Execute cmd, , adExecuteNoRecords + adAsyncExecute
End If
End Sub
我在這里是因為我正在考慮在類似的實時應用程序上使用asynchExecute。 在打開連接時將連接設置為空的問題是它可能無法正確釋放,並且您每創建一個10M都會創建一個新連接,這可能會導致內存泄漏。 測試時,應該檢查內存使用情況,以查看是否發生這種情況。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.