Невозможно передать аргумент в BackgroundWorker.RunWorkerAsync (System.MissingMemberException) - PullRequest
0 голосов
/ 26 февраля 2019

Я создаю программу выполнения заданий базы данных, которая позволит пользователям автоматизировать извлечение наборов данных из различных интерфейсов API и импортировать их в нашу базу данных.

После загрузки всех заданий при запуске приложения фоновый режимрабочий engine_JobTrigger запускает цикл, который несколько раз проверяет дату и время и сравнивает их с NextExecutionTime каждого задания в хранилище.Если срабатывает триггер, фоновый поток создает новый экземпляр BackgroundWorker (необходим для запуска других заданий), добавляет обработчик к DoWork на Job.ExecuteJob и начинает выполнение работника:

'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)

Есть ли у кого-нибудь какие-либо предложения??Я хотел бы продолжать использовать объект класса в качестве аргумента для моих BackgroundWorker s. Это поможет мне позже, когда я закончу и буду нуждаться в реализации новых функций.Как передать пользовательский класс в качестве аргумента для RunWorkerAsync в этом сценарии?Спасибо за любые советы заранее!

РЕДАКТИРОВАТЬ: Как только ошибка возникает, я могу успешно оценить e.Argument(0) и просмотреть значения в классе через IDE.

1 Ответ

0 голосов
/ 26 февраля 2019

Что это значит:

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 не индексируемый тип.

...