我正在尝试加载数据表异步,以便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