Cannot Pass Argument to BackgroundWorker.RunWorkerAsync (System.MissingMemberException)

0

I am creating a database job execution program that will allow users to automate data set retrieval from various API interfaces, and import them to our database.

Once all the jobs are loaded at application start, a background worker engine_JobTrigger starts a loop that repeatedly checks the date and time now and compares it to the NextExecutionTime of each job in the repository. If a trigger occurs, the background thread creates a new BackgroundWorker instance (required so that other jobs can be triggered to start), adds a handler to DoWork by Job.ExecuteJob, and begins the worker execution:

'Class definition for Job Executor Engine
Public Class engine_JobExecutorArgs
        Public SourceJob As Job = Nothing
        Public ExecutedAs As String = ""
        Public ExecuteStartTime As DateTime = Nothing
End Class
.............................................

engine_JobTrigger.DoWork \|/
.............................................
While Not engine.Cancel = True
   Dim jobsToStart As New List(Of Integer)
   If JobController.Jobs.Count > 0 Then
       For Each process As Job In JobController.Jobs
           If process.Schedule.isNowNextExecutionTime(process.LastExecutionTime) And Not process.isExecuting Then jobsToStart.Add(process.JobID)
       Next
   End If

   If jobsToStart.Count > 0 Then
       For Each JobID As Integer In jobsToStart
           'Argument passed to BackgroundWorker
           Dim newJobExecutorArgs As New engine_JobExecutorArgs() With {
               .SourceJob = JobController.GetJob(CType(JobID, Integer)),
               .ExecutedAs = Security.Principal.WindowsIdentity.GetCurrent().Name.ToString(),
               .ExecuteStartTime = Now
           }
           Dim newJobExecutor As New System.ComponentModel.BackgroundWorker()
           AddHandler newJobExecutor.DoWork, AddressOf newJobExecutorArgs.SourceJob.ExecuteJob
           AddHandler newJobExecutor.RunWorkerCompleted, AddressOf engine_JobExecutor_RunWorkerCompleted

           newJobExecutor.RunWorkerAsync(newJobExecutorArgs)
       Next
   Else
       Threading.Thread.Sleep(200)
   End If

End While

All is well and good until I enter the Job.ExecuteJob function and try to declare the argument passed to the newly created BackgroundWorker:

Dim inputArgs As MainWindow.engine_JobExecutorArgs = DirectCast(e.Argument(0), MainWindow.engine_JobExecutorArgs)
System.MissingMemberException
  HResult=0x80131512
  Message=No default member found for type 'engine_JobExecutorArgs'.
  Source=Microsoft.VisualBasic
  StackTrace:
   at Microsoft.VisualBasic.CompilerServices.Symbols.Container.GetMembers(String& MemberName, Boolean ReportErrors)
   at Microsoft.VisualBasic.CompilerServices.NewLateBinding.CallMethod(Container BaseReference, String MethodName, Object[] Arguments, String[] ArgumentNames, Type[] TypeArguments, Boolean[] CopyBack, BindingFlags InvocationFlags, Boolean ReportErrors, ResolutionFailure& Failure)
   at Microsoft.VisualBasic.CompilerServices.NewLateBinding.InternalLateIndexGet(Object Instance, Object[] Arguments, String[] ArgumentNames, Boolean ReportErrors, ResolutionFailure& Failure, Boolean[] CopyBack)
   at Microsoft.VisualBasic.CompilerServices.NewLateBinding.ObjectLateInvokeDefault(Object Instance, Object[] Arguments, String[] ArgumentNames, Boolean ReportErrors, Boolean[] CopyBack)
   at Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateIndexGet(Object Instance, Object[] Arguments, String[] ArgumentNames)
   at Mastermind.Job.ExecuteJob(Object sender, DoWorkEventArgs e) in ...Mastermind\JobObject.vb:line 184
   at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)
   at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)

Does anybody have any suggestions? I would love to keep using a class object as an argument with my BackgroundWorkers, It would help me later when I finish and need to implement new features. How do I pass a custom class as an argument to 'RunWorkerAsync` in this scenario? Thank you for any advice in advance!

EDIT: Once the error occurs, I can successfully evaluate e.Argument(0) and view the values within the class via the IDE.

vb.net
asynchronous
exception
arguments
backgroundworker
asked on Stack Overflow Feb 26, 2019 by Matthew Wendel

1 Answer

0

What is this about:

Dim inputArgs As MainWindow.engine_JobExecutorArgs = DirectCast(e.Argument(0), MainWindow.engine_JobExecutorArgs)

Why are you using e.Argument(0)? e.Argument is just an Object reference and it refers to the object that you passed in. The object you passed in is type engine_JobExecutorArgs:

Dim newJobExecutorArgs As New engine_JobExecutorArgs()

'...

newJobExecutor.RunWorkerAsync(newJobExecutorArgs)

Can that type be indexed, i.e. is it a list type? No it isn't, so what would you expect indexing it to do? e.Argument refers to an object of that type so you should be casting it as that type:

Dim inputArgs As MainWindow.engine_JobExecutorArgs = DirectCast(e.Argument, MainWindow.engine_JobExecutorArgs)

There's no indexing to be done, which is what the error message is telling you. You are trying to index a late-bound reference and it's telling you that there is no such member. If you had Option Strict On then you would be told that indexing e.Argument is not allowed because Object is not an indexable type.

answered on Stack Overflow Feb 26, 2019 by jmcilhinney

User contributions licensed under CC BY-SA 3.0