无法将参数传递给 BackgroundWorker.RunWorkerAsync (System.MissingMemberException)
Cannot Pass Argument to BackgroundWorker.RunWorkerAsync (System.MissingMemberException)
我正在创建一个数据库作业执行程序,允许用户从各种 API 接口自动检索数据集,并将它们导入我们的数据库。
在应用程序启动时加载所有作业后,后台工作人员 engine_JobTrigger
会启动一个循环,反复检查现在的日期和时间,并将其与存储库中每个作业的 NextExecutionTime
进行比较.如果触发发生,后台线程创建一个新的 BackgroundWorker
实例(需要这样才能触发其他作业启动),通过 Job.ExecuteJob
添加一个处理程序到 DoWork
,并启动 worker执行:
'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
一切都很好,直到我进入 Job.ExecuteJob
函数并尝试声明传递给新创建的参数 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)
有人有什么建议吗?我很乐意继续使用 class 对象作为我的 BackgroundWorker
的参数,它会在我完成并需要实现新功能时帮助我。在这种情况下,如何将自定义 class 作为参数传递给“RunWorkerAsync”?感谢您提前提出任何建议!
编辑: 一旦发生错误,我可以成功计算 e.Argument(0)
并通过 IDE 查看 class 中的值。
这是关于什么的:
Dim inputArgs As MainWindow.engine_JobExecutorArgs = DirectCast(e.Argument(0), MainWindow.engine_JobExecutorArgs)
为什么要使用 e.Argument(0)
? e.Argument
只是一个 Object
引用,它指的是您传入的对象。您传入的对象类型为 engine_JobExecutorArgs
:
Dim newJobExecutorArgs As New engine_JobExecutorArgs()
'...
newJobExecutor.RunWorkerAsync(newJobExecutorArgs)
该类型是否可以被索引,即它是列表类型吗?不,它不是,那么你希望索引它做什么? e.Argument
指的是该类型的对象,因此您应该将其转换为该类型:
Dim inputArgs As MainWindow.engine_JobExecutorArgs = DirectCast(e.Argument, MainWindow.engine_JobExecutorArgs)
没有索引要完成,这是错误消息告诉您的内容。您正在尝试索引一个后期绑定引用,它告诉您没有这样的成员。如果你有 Option Strict On
那么你会被告知索引 e.Argument
是不允许的,因为 Object
不是可索引的类型。
我正在创建一个数据库作业执行程序,允许用户从各种 API 接口自动检索数据集,并将它们导入我们的数据库。
在应用程序启动时加载所有作业后,后台工作人员 engine_JobTrigger
会启动一个循环,反复检查现在的日期和时间,并将其与存储库中每个作业的 NextExecutionTime
进行比较.如果触发发生,后台线程创建一个新的 BackgroundWorker
实例(需要这样才能触发其他作业启动),通过 Job.ExecuteJob
添加一个处理程序到 DoWork
,并启动 worker执行:
'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
一切都很好,直到我进入 Job.ExecuteJob
函数并尝试声明传递给新创建的参数 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)
有人有什么建议吗?我很乐意继续使用 class 对象作为我的 BackgroundWorker
的参数,它会在我完成并需要实现新功能时帮助我。在这种情况下,如何将自定义 class 作为参数传递给“RunWorkerAsync”?感谢您提前提出任何建议!
编辑: 一旦发生错误,我可以成功计算 e.Argument(0)
并通过 IDE 查看 class 中的值。
这是关于什么的:
Dim inputArgs As MainWindow.engine_JobExecutorArgs = DirectCast(e.Argument(0), MainWindow.engine_JobExecutorArgs)
为什么要使用 e.Argument(0)
? e.Argument
只是一个 Object
引用,它指的是您传入的对象。您传入的对象类型为 engine_JobExecutorArgs
:
Dim newJobExecutorArgs As New engine_JobExecutorArgs()
'...
newJobExecutor.RunWorkerAsync(newJobExecutorArgs)
该类型是否可以被索引,即它是列表类型吗?不,它不是,那么你希望索引它做什么? e.Argument
指的是该类型的对象,因此您应该将其转换为该类型:
Dim inputArgs As MainWindow.engine_JobExecutorArgs = DirectCast(e.Argument, MainWindow.engine_JobExecutorArgs)
没有索引要完成,这是错误消息告诉您的内容。您正在尝试索引一个后期绑定引用,它告诉您没有这样的成员。如果你有 Option Strict On
那么你会被告知索引 e.Argument
是不允许的,因为 Object
不是可索引的类型。