异步操作已经完成

时间:2012-12-19 11:43:58

标签: vb.net service-broker asynchronous

我有一个带有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)上发布了同样的问题,因为我尝试了其他解决方案但没有成功,因此需要一些关于这是否可行的建议以及如果可能的话。

0 个答案:

没有答案