0

I am running a BackgroundWorker, and want to report its progress. In the example below I create a test list which the BackgroundWorker then iterates through. The problem lies in the line 'sender.ReportProgress(i)'. If I have Option Strict on, it does not like my use of 'i' due to Late Binding issues. Is there any alternative way to code this and avoid that issue?

    Public Class Form1

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        ' Configuring for Background Workers
        Control.CheckForIllegalCrossThreadCalls = False

        Dim MyList As New List(Of String)
        For a As Integer = 0 To 100
            MyList.Add(CStr(a))
        Next
    End Sub

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        Dim bgw As New System.ComponentModel.BackgroundWorker
        bgw.WorkerReportsProgress = True
        bgw.WorkerSupportsCancellation = True
        AddHandler bgw.DoWork, AddressOf bgw_DoWork
        ' I create a BackgroundWorker here rather than add one in the toolbox so that I can specify the Handler and use different Handler routines for different part of a large program.

        Button1.Enabled = False
        Dim progress As New Progress(bgw)
        progress.ShowDialog()
        Button1.Enabled = True
    End Sub

    Private Sub bgw_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs)
        For i = 0 To MyList.Count -1
            Label1.Text = MyList(i)
            sender.ReportProgress(i)
            System.Threading.Thread.Sleep(200)
            Label1.Refresh()
        Next

    End Sub

End Class


Public Class Progress
    Private WithEvents _BGW As System.ComponentModel.BackgroundWorker

    Public Sub New(ByVal BGW As System.ComponentModel.BackgroundWorker)
        _BGW = BGW
        InitializeComponent()
    End Sub

    Private Sub frmProgress_Shown(sender As Object, e As System.EventArgs) Handles Me.Shown
        If Not IsNothing(_BGW) Then
            _BGW.RunWorkerAsync()
        End If
    End Sub

    Private Sub _BGW_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles _BGW.ProgressChanged
        ProgressBar1.Value = e.ProgressPercentage
        Label1.Text = e.ProgressPercentage
    End Sub

    Private Sub _BGW_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles _BGW.RunWorkerCompleted
        Me.Close()
    End Sub
End Class
Tim Makins
  • 394
  • 4
  • 12
  • It is not the `i` it has a problem with, it is the `ReportProgress` method - `System.Object` has no such method. There are several other issues. On a side note, you should visit the [tour] page - your past 3 posts have 5 answers but all remain open because none of the answers have been accepted, – Ňɏssa Pøngjǣrdenlarp May 29 '17 at 15:09
  • Thanks for your comments. What are the other issues? OK about the Acceptance - I hadn't realised that I was supposed to. – Tim Makins May 29 '17 at 16:20

2 Answers2

1
CType(sender, BackgroundWorker).ReportProgress(i)
Mike
  • 419
  • 4
  • 11
  • Just a little note: It is better (and faster) to use [**`DirectCast`**](https://learn.microsoft.com/en-us/dotnet/articles/visual-basic/language-reference/operators/directcast-operator) when the object type is known. `CType` is supposed to be used when converting to a _**different**_ type (for instance converting a `Byte` to an `Integer`, although this is usually done implicitly when not using `Option Strict`). – Visual Vincent May 29 '17 at 22:28
  • The difference between the two is that `CType` tries to use [**conversion operators**](https://learn.microsoft.com/en-us/dotnet/articles/visual-basic/programming-guide/language-features/procedures/how-to-define-a-conversion-operator) to perform a conversion, and if that fails it'll try casting instead. `DirectCast` only does casting and is therefore much faster than `CType` when you are not looking to convert an object to a different type. – Visual Vincent May 29 '17 at 22:35
1

Also, if you want to do multiple actions with it, then create a local reference variable like this:

Private Sub bgw_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs)

    Dim bgw As System.ComponentModel.BackgroundWorker = DirectCast(sender, System.ComponentModel.BackgroundWorker)

    ' ... now you can use "bgw" multiple times below instead of casting each time ...

    For i = 0 To MyList.Count -1
        Label1.Text = MyList(i)
        bgw.ReportProgress(i)
        bgw.SomethingElse()
        bgw.MoreStuff()
        System.Threading.Thread.Sleep(200)
        Label1.Refresh()
    Next
End Sub

Obviously this isn't necessary in your case, just an FYI...

Idle_Mind
  • 38,363
  • 3
  • 29
  • 40