You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

扫描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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 16:07:40