1

I have an app that's doing lots of time checks and looping through datatables etc checking for certain values at certain times etc.

The end result is that I have a list(of string) that contains the names of the "schedules" that need running at a particular time. Those names correspond to the names of a set of background workers.

I'm wondering if there is any way I can loop through that list and, using the backgroundworker name which is a string variable, call the corresponding background workers RunWorkerAsync method?

The background workers are already declared before runtime, and their names are static - matched by the names in the list.

I've been looking at the CallByName function, but cant find any usage examples of documentation that show it used in this way, so i'm not sure if I'm heading down a dead end there.

 For Each schedule In run_these_schedules
 CallByName(schedule, BackgroundWorker.RunWorkerAsync)
 Next 

Any help appreciated in advanced!

John
  • 755
  • 1
  • 18
  • 46
  • Probably, but you need to show some code. Are the backgroundworkers declared in your code as variables whose names are the strings in your list? If so are they class level properties or local Dims? Need to see it in code – djv Dec 13 '21 at 22:15
  • Yeah but how are the actual backgroundworkers defined? – djv Dec 13 '21 at 22:21
  • Thanks djv - I've updated my question and will continue to do so. The background workers are already declared and are class level. :) – John Dec 13 '21 at 22:22
  • 1
    Are the `schedule` in each of those run_these_schedules the names of backgroundworkers, or names of their corresponding methods? – djv Dec 13 '21 at 22:23
  • @djv -They are added in design as an object. This app is a .net windows service, so they are the only object in design. – John Dec 13 '21 at 22:23
  • the schedule is the name of the background worker – John Dec 13 '21 at 22:24

2 Answers2

4

In the designer they will be declared by default as

Friend WithEvents BackgroundWorker1 As ComponentModel.BackgroundWorker
Friend WithEvents BackgroundWorker2 As ComponentModel.BackgroundWorker
' ...

Looks like a field, however once WithEvents gets added this is a property

So we can use Reflection and get the properties by name

Dim run_these_schedules As New List(Of String) From {"BackgroundWorker1", "BackgroundWorker2"}
For Each schedule In run_these_schedules
    Dim t = GetType(Service1)
    Dim pi = t.GetProperty(schedule,
                           Reflection.BindingFlags.Instance Or
                           Reflection.BindingFlags.Public Or
                           Reflection.BindingFlags.NonPublic)
    Dim bw = DirectCast(pi.GetValue(Me), BackgroundWorker)
    bw.RunWorkerAsync()
Next
djv
  • 15,168
  • 7
  • 48
  • 72
3

Extending djv's excellent answer, you could search the form for all backgroundworkers in the Load() event and store them in a Dictionary(Of String, BackgroundWorker) for fast lookup:

Private BWs As New Dictionary(Of String, BackgroundWorker)

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    For Each pi As Reflection.PropertyInfo In Me.GetType.GetProperties(Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic)
        Dim obj As Object = pi.GetValue(Me)
        If TypeOf (obj) Is BackgroundWorker Then
            Dim bw As BackgroundWorker = DirectCast(obj, BackgroundWorker)
            BWs.Add(pi.Name, bw)
        End If
    Next
End Sub

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    Dim run_these_schedules() As String = {"BackgroundWorker1", "BackgroundWorker2", "UnicornsExist"}
    For Each schedule In run_these_schedules
        If BWs.ContainsKey(schedule) Then
            BWs(schedule).RunWorkerAsync()
        Else
            Debug.Print("Schedule not found: " & schedule)
        End If
    Next
End Sub
Idle_Mind
  • 38,363
  • 3
  • 29
  • 40