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 BackgroundWorker
s, 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.
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.
User contributions licensed under CC BY-SA 3.0