我有一个带有DataGridView的VB.net应用程序,显示作业列表,从SQL查询检索到DataTable,然后是DataView,最后是DataGridView.DataSource的BindingSource。我最近在设置中添加了SqlNotificationRequest功能,因此当用户B对列表中的作业执行操作时,用户A会立即更新。
我使用这篇MSDN文章(http://msdn.microsoft.com/en-US/library/3ht3391b(v=vs.80).aspx)作为我开发的基础,它运行正常。当用户想要更改显示作业的SQL查询的参数(例如显示的日期)时,会出现问题。目前我正在使用新的通知创建一个新的SqlCommand但是在用户更改日期几次(比如说30)之后,但没有数据更改,当通知超时发生时,当回调处理程序尝试使用EndExecuteReader时,我收到上述错误。我的回调处理程序如下:
Private Sub OnSalesReaderComplete(ByVal asynResult As IAsyncResult)
' You may not interact with the form and its contents
' from a different thread, and this callback procedure
' is all but guaranteed to be running from a different thread
' than the form. Therefore you cannot simply call code that
' updates the UI.
' Instead, you must call the procedure from the form's thread.
' This code will use recursion to switch from the thread pool
' to the UI thread.
If Me.InvokeRequired Then
myStatus.addHistory("OnSalesReaderComplete - Background", "Sub")
Dim switchThreads As New AsyncCallback(AddressOf Me.OnSalesReaderComplete)
Dim args() As Object = {asynResult}
Me.BeginInvoke(switchThreads, args)
Exit Sub
End If
' At this point, this code will run on the UI thread.
Try
myStatus.addHistory("OnSalesReaderComplete - UI", "Sub")
Dim sourceText, rSalesId As String
waitInProgressSales = False
Trace.WriteLine(String.Format("Sales:asynResult.IsCompleted1: {0}", asynResult.IsCompleted.ToString), "SqlNotificationRequest")
Trace.WriteLine(String.Format("Sales:asynResult.CompletedSynchronously: {0}", asynResult.CompletedSynchronously.ToString), "SqlNotificationRequest")
Dim reader As SqlDataReader = DirectCast(asynResult.AsyncState, SqlCommand).EndExecuteReader(asynResult)
Trace.WriteLine(String.Format("Sales:asynResult.IsCompleted2: {0}", asynResult.IsCompleted.ToString), "SqlNotificationRequest")
Do While reader.Read
' Empty queue of messages.
' Application logic could parse
' the queue data to determine why things.
'For i As Integer = 0 To reader.FieldCount - 1
' 'Debug.WriteLine(reader(i).ToString())
' Console.WriteLine(reader(i).ToString)
'Next
Dim bytesQN As SqlBytes = reader.GetSqlBytes(reader.GetOrdinal("message_body"))
Dim rdrXml As XmlReader = New XmlTextReader(bytesQN.Stream)
Do While rdrXml.Read
Select Case rdrXml.NodeType
Case XmlNodeType.Element
Select Case rdrXml.LocalName
Case "QueryNotification"
sourceText = rdrXml.GetAttribute("source")
Case "Message"
rSalesId = rdrXml.ReadElementContentAsString
End Select
End Select
Loop
Loop
reader.Close()
' The user can decide to request
' a new notification by
' checking the check box on the form.
' However, if the user has requested to
' exit, we need to do that instead.
If exitRequestedSales Then
'Me.Close()
commandSales.Notification = Nothing
Else
Select Case sourceText.ToLower
Case "data"
Trace.WriteLine(String.Format("SalesId: {0}, data notification", rSalesId), "SqlNotificationRequest")
Call GetSalesData(True, action.REATTACH)
Case "timeout"
'check timeout is for this user and relates to current wait thread
Select Case salesId = rSalesId
Case True
Trace.WriteLine(String.Format("SalesId: {0}, timeout - current", rSalesId), "SqlNotificationRequest")
Call GetSalesData(True, False)
Case False
Trace.WriteLine(String.Format("SalesId: {0}, timeout - old", rSalesId), "SqlNotificationRequest")
Me.ListenSales()
End Select
End Select
End If
Catch ex As Exception
Call errorHandling(ex, "OnSalesReaderComplete", "Sub")
End Try
End Sub
问题似乎是我只刷新数据并更新通知请求(使用GetSalesData),当通知是由更新(“数据”)或超时是当前请求时。在其他通知上,应用程序调用Me.ListenSales,它创建一个SQL命令“WAITFOR(RECEIVE * FROM [QueueMessage])”并根据MSDN文章启动回调侦听器。如果我删除Me.ListenSales行,一旦收到通知,这不是由于数据或当前查询的超时,应用程序就会停止侦听通知。
我也在MSDN论坛(http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataproviders/thread/0f7a636d-0c9b-4b39-b341-6becf13873dc)上发布了同样的问题,因为我尝试了其他解决方案但没有成功,因此需要一些关于这是否可行的建议以及如果可能的话。