backgroundWorker仅在取消

时间:2018-06-12 11:30:25

标签: vb.net multithreading backgroundworker

我希望在表单上显示一个'dinamic label',只需在另一个正在运行的线程中写入'Loading'。 标签应在此模式下更改:

L,Lo,Loa,Load,Loadi,Loadin,Loading,oading,ading,ding,ing,ng,g

我编写了代码,但是只有在BackGroundWorker.CancellationPending = True时才调用'BackGroundWorker_ProgressChanged事件。

此时,发送所有更新。

这里是代码

Public Class Form1

  Dim WithEvents bgw As New BackgroundWorker
  Dim WithEvents I_MyClass As MyNewClass
  Dim lLoading As New Label
  Dim WithEvents T As New Timer

  Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    bgw.WorkerReportsProgress = True
    bgw.WorkerSupportsCancellation = True
    I_MyClass = New MyNewClass
    AddHandler I_MyClass.Start, AddressOf StartLoading
    AddHandler I_MyClass.Stop, AddressOf StopLoading

    With lLoading
        .Size = New Size(120, 25)
        .Location = New Point(10, 10)
    End With
    Me.Controls.Add(lLoading)

    T.Interval = 1000
    AddHandler T.Tick, AddressOf T_Tick

    T.Start()
  End Sub

  Private Sub T_Tick(sender As Object, e As EventArgs) Handles T.Tick
    T.Stop()
    I_MyClass.StartLoading()
  End Sub

  Public Sub StartLoading()
    If bgw.IsBusy Then Exit Sub
    bgw.RunWorkerAsync()
  End Sub

  Public Sub StopLoading()
    bgw.CancelAsync()
  End Sub

  Private Sub bgw_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bgw.DoWork
    Dim worker As System.ComponentModel.BackgroundWorker = CType(sender, System.ComponentModel.BackgroundWorker)

    Dim i As Integer = 1
    Dim loadingString As String = "Loading......."
    Do
        If (worker.CancellationPending = True) Then
            e.Cancel = True
            Exit Do
        Else
            Threading.Thread.Sleep(500)
            worker.ReportProgress(i)
            If i = loadingString.Count Then i = 1 Else i += 1
        End If
    Loop
  End Sub

  Private Sub bgw_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles bgw.ProgressChanged
    Dim loadingString As String = "Loading......."
    Dim i As Integer = e.ProgressPercentage
    Dim l As Integer = lLoading.Text.Count
    If l < i Then
        lLoading.Text = loadingString.Substring(0, i)
    Else
        lLoading.Text = loadingString.Substring(i, l - i)
    End If
  End Sub

End Class

Public Class MyNewClass
  Sub New()

  End Sub
  Public Event Start()
  Public Event [Stop]()

  Public Sub StartLoading()
    RaiseEvent Start()
    ' simulate download
    For a = 0 To 10
        Threading.Thread.Sleep(1000)
    Next a
    RaiseEvent Stop()
  End Sub
End Class

不明白为什么'BackGroundWorker_ProgressChanged事件没有被调用报告部分进度,但只有在BackGroundWorker.CancellationPending = True时才调用它。

P.S。也欢迎使用c#help。

2 个答案:

答案 0 :(得分:2)

  

不明白为什么它不被称为BackGroundWorker_ProgressChanged事件报告部分进展

因为你有一个计时器可以启动非常非阻塞,非常非同步的StartLoading方法。

您似乎从主线程中调用此代码:

    For a = 0 to 10
        Threading.Thread.Sleep(1000)
    Next a

所以你的应用程序将是完全失聪和愚蠢的11秒。没时间进行屏幕更新或进度事件,我们正忙着睡觉。

答案 1 :(得分:1)

感谢Bommelding,我注意到我忘了在一个单独的线程中开始下载,所以Bommelding让我注意到,指令'threading.thread.sleep()正在停止Label更新 代码更正了。

Imports System.ComponentModel

Public Class Form1

  Dim WithEvents bgw As New BackgroundWorker
  Dim WithEvents I_MyClass As MyNewClass
  Dim lLoading As New Label
  Dim WithEvents T As New Timer

  Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    bgw.WorkerReportsProgress = True
    bgw.WorkerSupportsCancellation = True
    I_MyClass = New MyNewClass
    AddHandler I_MyClass.Start, AddressOf StartLoading
    AddHandler I_MyClass.Stop, AddressOf StopLoading

    With lLoading
        .Size = New Size(120, 25)
        .Location = New Point(10, 10)
        .TextAlign = ContentAlignment.MiddleCenter
        .Tag = "Loading"
        For a = 0 To CStr(.Tag).Count - 1
            .Text += " "
        Next
    End With
    Me.Controls.Add(lLoading)

    T.Interval = 1000
    AddHandler T.Tick, AddressOf T_Tick

    T.Start()
  End Sub

  Private Sub T_Tick(sender As Object, e As EventArgs) Handles T.Tick
    T.Stop()
    I_MyClass.StartLoading()
  End Sub

  Public Sub StartLoading()
    If bgw.IsBusy Then Exit Sub
    bgw.RunWorkerAsync(CStr(lLoading.Tag).Count - 1)
  End Sub

  Public Sub StopLoading()
    bgw.CancelAsync()
  End Sub

  Private Sub bgw_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bgw.DoWork
    Dim worker As System.ComponentModel.BackgroundWorker = CType(sender, System.ComponentModel.BackgroundWorker)
    Dim limit As Integer = CInt(e.Argument)
    Dim i As Integer = 0
    Do
        If (worker.CancellationPending = True) Then
            e.Cancel = True
            Exit Do
        Else
            Threading.Thread.Sleep(100)
            worker.ReportProgress(i)
            If i = limit Then i = 0 Else i += 1
        End If
    Loop
    i = Nothing
    limit = Nothing
    worker = Nothing
  End Sub

  Private Sub bgw_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles bgw.ProgressChanged
    Dim loadingString As String = CStr(lLoading.Tag)

    Dim i As Integer = e.ProgressPercentage
    'Dim l As Integer = lLoading.Text.Count
    If lLoading.Text(i) <> loadingString(i) Then
        Mid(lLoading.Text, i + 1, 1) = loadingString(i)
    Else
        Mid(lLoading.Text, i + 1, 1) = " "
    End If
    i = Nothing
    loadingString = Nothing
  End Sub

  Private Sub bgw_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles bgw.RunWorkerCompleted
    For a = 0 To CStr(lLoading.Tag).Count - 1
        lLoading.Text += " "
    Next
  End Sub
End Class

Public Class MyNewClass
  Sub New()
    bgwDoSameWork.WorkerReportsProgress = True
    bgwDoSameWork.WorkerSupportsCancellation = True
  End Sub
  Public Event Start()
  Public Event [Stop]()
  Private WithEvents bgwDoSameWork As New BackgroundWorker


  Public Sub StartLoading()
    ' simulate download
    If bgwDoSameWork.IsBusy = False Then
        RaiseEvent Start()
        bgwDoSameWork.RunWorkerAsync()
    End If

  End Sub

  Private Sub bgwDoSameWork_DoWork(sender As Object, e As DoWorkEventArgs) Handles bgwDoSameWork.DoWork
    For a = 0 To 10
        Threading.Thread.Sleep(1000)
    Next a
  End Sub

  Private Sub bgwDoSameWork_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles bgwDoSameWork.RunWorkerCompleted
    RaiseEvent Stop()
  End Sub
End Class