扫描DataTable时如何同时保持WaitCursor并显示DataGridView进度
解决BackgroundWorker场景下等待光标不生效的问题
首先咱们来拆解下问题根源:你之前在Button1_Click里设置Cursor.Current = Cursors.WaitCursor后,立刻调用了BW.RunWorkerAsync——这是异步操作,UI线程不会被阻塞,很快就会回到空闲状态,导致光标自动恢复成默认样式,后台线程运行期间UI线程并没有维持等待光标的状态。
正确解决方案
核心思路是设置窗体全局光标,而非仅设置当前鼠标位置的临时光标,同时确保后台任务无论成功、失败或被取消,都能恢复正常光标样式。
修改后的完整代码如下:
WithEvents BW As New BackgroundWorker With {.WorkerReportsProgress = True, .WorkerSupportsCancellation = True} Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click ' 设置整个窗体的光标为等待状态 Me.Cursor = Cursors.WaitCursor ' 禁用按钮防止重复点击(可选但推荐) Button1.Enabled = False BW.RunWorkerAsync(vCountries) End Sub Private Sub BW_DoWork(sender As Object, e As DoWorkEventArgs) Handles BW.DoWork Dim bw As BackgroundWorker = CType(sender, BackgroundWorker) Dim vCountries As DataView = e.Argument For k = 0 To vCountries.Count - 1 ' 检查是否取消任务(可选) If bw.CancellationPending Then e.Cancel = True Exit For End If bw.ReportProgress(k) ScannerPageOne(vCountries.Item(k).Row) Next End Sub Private Sub BW_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BW.RunWorkerCompleted ' 恢复窗体光标为默认样式 Me.Cursor = Cursors.Default ' 重新启用按钮 Button1.Enabled = True ' 处理任务完成的各种状态(可选) If e.Cancelled Then MessageBox.Show("任务已取消") ElseIf e.Error IsNot Nothing Then MessageBox.Show($"任务执行出错:{e.Error.Message}") End If End Sub Private Sub BW_ProgressChanged(ByVal sender As System.Object, ByVal e As ProgressChangedEventArgs) Handles BW.ProgressChanged ' 重置上一行的背景色 If e.ProgressPercentage > 0 Then DgView1.Rows(e.ProgressPercentage - 1).Cells(CoName).Style.BackColor = DgView1.DefaultCellStyle.BackColor End If ' 设置当前行的背景色标记进度 DgView1.Rows(e.ProgressPercentage).Cells(CoName).Style.BackColor = Color.GreenYellow ' 滚动到当前行(优化原逻辑的错误判断) If e.ProgressPercentage < DgView1.FirstDisplayedScrollingRowIndex OrElse e.ProgressPercentage > DgView1.FirstDisplayedScrollingRowIndex + DgView1.DisplayedRowCount(False) - 1 Then DgView1.FirstDisplayedScrollingRowIndex = e.ProgressPercentage End If End Sub
关键修改点说明
- 光标设置方式替换:用
Me.Cursor = Cursors.WaitCursor替代Cursor.Current = Cursors.WaitCursor,这样整个窗体范围内的光标都会保持等待状态,直到手动恢复。 - 防止重复触发:启动后台任务时禁用按钮,避免用户重复点击导致多任务并行,任务完成后再重新启用。
- 完善异常与取消处理:在
RunWorkerCompleted中覆盖任务取消、异常的场景,确保光标在任何情况下都能恢复正常。 - 修复进度滚动逻辑:修正原代码中滚动判断的错误(误用
DisplayedColumnCount应为DisplayedRowCount),保证当前处理行始终处于可见区域。
内容的提问来源于stack exchange,提问作者shemmy
相关产品推荐
相关产品推荐

