使用进度条取消异步任务会导致使用vb.net发生targetinvocationexception错误

时间:2017-04-22 14:30:23

标签: vb.net async-await progress-bar cancellationtokensource

我正在尝试加载数据表异步,以便UI保持响应。我已经使用dt.RowChanged事件来处理返回进度条和标签的报告进度。但是,单击“停止”按钮时,会导致以下错误: 类型为' System.Reflection.TargetInvocationException'的未处理异常发生在mscorlib.dll。

我不确定如何找到解决此问题的方法。任何指导表示赞赏。以下是使用AdventureWorks DB的示例项目中的代码

Imports System.Threading
Imports System.Threading.Tasks

Public Class AsyncProgressCancel
    Public strConnectionString As String = "data source=010XXX01;initial catalog=AdventureWorks2012;integrated security=SSPI;"
    Private dt As DataTable
    Private ds As DataSet
    Dim dataset
    Dim RecordCount As Integer = 1000000
    Dim Counter As Integer
    Dim myProgress As Progress(Of Integer)
    Private Delegate Sub AsyncDelegate(ByVal value As Integer)
    Private ProgressUpdater As New AsyncDelegate(AddressOf UpdateProgress)
    Private TargetCounter As Integer = 1000
    Private cts As CancellationTokenSource
    Private Cancelled As Boolean

    Private Sub AsyncProgressCancel_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        ProgressBar1.Visible = False
        lblProgress.Visible = False
        btnStop.Enabled = False
    End Sub
    Private Async Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click


        btnStart.Enabled = False
        btnStop.Enabled = True
        Cancelled = False

        ProgressBar1.Value = 0
        ProgressBar1.Maximum = RecordCount
        ProgressBar1.Visible = True
        lblProgress.Visible = True
        DataGridView1.Enabled = False
        cts = New CancellationTokenSource()

        Try
            Dim completed As Boolean = Await LoadDataAsync(myProgress, cts.Token)

        Catch ex As OperationCanceledException
            lblProgress.Text = "Retrieve cancelled."
            DataGridView1.DataSource = Nothing
            DataGridView1.Enabled = True
            btnStop.Enabled = False
            btnStart.Enabled = True
            ProgressBar1.Visible = False
        Catch ex As Exception
            MsgBox(ex)
        End Try

    End Sub
    Private Sub UpdateProgress(ByVal value As Integer)

        If Cancelled = True Then
            cts.Cancel()
        Else
            If ProgressBar1.InvokeRequired Then
                ProgressBar1.Invoke(ProgressUpdater, New Object() {value})
            ElseIf value > ProgressBar1.Maximum Then
                value = ProgressBar1.Maximum
                ProgressBar1.Value = value
            End If

            lblProgress.Text = Math.Round((value / RecordCount) * 100).ToString & "% complete"      '"Step Number: " & myInt.ToString
            ProgressBar1.Value = value

        End If

    End Sub

    Private Async Function LoadDataAsync(ByVal myProgress As IProgress(Of Integer), token As CancellationToken) As Task(Of Boolean)

        Dim comSQL As SqlClient.SqlCommand
        Dim strSQL As String
        Dim da As SqlClient.SqlDataAdapter
        Dim dt As New DataTable
        Dim ReturnValue As Boolean


        Try
            DataGridView1.Enabled = Await Task(Of Boolean).Run(Function()
                                                                   Using conn As SqlClient.SqlConnection = New SqlClient.SqlConnection(strConnectionString)
                                                                       conn.Open()

                                                                       strSQL = "SELECT * FROM (SELECT TOP 1000000 PRODUCTION.PRODUCT.* FROM sales.SalesOrderDetail CROSS JOIN production.Product) A"
                                                                       comSQL = New SqlClient.SqlCommand(strSQL, conn)
                                                                       da = New SqlClient.SqlDataAdapter(comSQL)

                                                                       AddHandler dt.RowChanged, Sub(obj, e)

                                                                                                     If e.Action.Add Then
                                                                                                         Counter = obj.Rows.Count

                                                                                                         If Counter > RecordCount Then
                                                                                                             Counter = RecordCount
                                                                                                         Else
                                                                                                             Counter = Counter + 1        ' Math.Ceiling(0.1 * RecordCount)
                                                                                                         End If
                                                                                                     End If

                                                                                                     If token.IsCancellationRequested = True Then
                                                                                                         token.ThrowIfCancellationRequested()


                                                                                                     Else
                                                                                                         If Counter = TargetCounter Then
                                                                                                             UpdateProgress(Counter)
                                                                                                             TargetCounter = TargetCounter + 1000
                                                                                                         End If
                                                                                                     End If
                                                                                                 End Sub


                                                                       If Counter > 0 Then
                                                                           myProgress.Report(Counter)
                                                                       End If



                                                                       da.Fill(dt)
                                                                       dataset = dt

                                                                       ReturnValue = True

                                                                       Return ReturnValue
                                                                   End Using
                                                               End Function, token)
        Catch ex As Exception
            MsgBox(ex)
        End Try

    End Function

    Private Sub btnStop_Click(sender As Object, e As EventArgs) Handles btnStop.Click
        Try
            If Not cts Is Nothing Then
                cts.Cancel()    
            End If    
        Catch ex As Exception
            MsgBox(ex)
        End Try    
    End Sub

End Class

0 个答案:

没有答案