0

So, I originally had this section of code where the parent caller in the caller tree is my main window's load function. Now this gave me a beginInvoke (Your windows control is not yet initialized and it tries to reference it) error whenever I restart my OS. Many suggested moving it to the form shown event, to add a boolean if something was loaded, but this never got rid of the problem. I ended up just removing the multithreading since I was pulling my hair out.

     'send broadcast on network    
    Dim tasksArr(1) As Task
    Dim brand1SearchTask= Task(Of List(Of device)).Factory.StartNew(Function() getbrand1())
    Dim brand2SearchTask= Task(Of List(Of device)).Factory.StartNew(Function() getbrand2())

    Try
        tasksArr(0) = brand1SearchTask
        tasksArr(1) = brand2SearchTask
        Task.WaitAll(tasksArr)
    Catch ex As Exception

    End Try

    Try
        Try
            deviceList.AddRange(brand1SearchTask.Result())
        Catch ex As Exception
        End Try

        deviceList.AddRange(brand2SearchTask.Result())
    Catch ex As Exception

    End Try

This code is within a function in a separate class called NetworkSearch.FindDevices(). It is called from the load function in the MainWindow_Load.

So from what I learned the main problem is that in the tasks' .start or begin call it calls .Invoke, and if my form isn't initialized at that time it will complain from windows. One solution I had was to create a separate module and then create a New() form of my main window. That removed the error, but any other forms from that window (like clicking a button to launch another form) wasn't initialized as well and gave me a null exception.

My question: What is a good way to check if I am initialized yet in the tasks or threading environment and then waiting to go into my threads? If this were a control I would create a delegate function and edit that, but here this isn't really touching the GUI directly.

What I have tried:

-Creating a module and making a New() main form from it, but then the rest of my forms were nothing objects when launched from there

-Moved into main's form shown (begin invoke error still happened)

-Added a private sub My_application startup to handle me.startup with a My.Settings.Loadfinished boolean, did not remove it.

-Added a "mainwindow.invokerequired" check, complained only on runtime that it needed to say "me" instead

Kat
  • 2,460
  • 2
  • 36
  • 70

1 Answers1

0

If you want to design a class to be able to execute code specifically on the UI thread when it has no direct knowledge of the UI then you have two main options:

  1. Declare a SynchronizingObject property in your class of type ISynchronizeInvoke. Internally, test whether that property is Nothing and, if it's not, use its InvokeRequired property and Invoke/BeginInvoke method. From the outside, you can assign a form or other control to that property. That is how the FileSystemWatcher and Timers.Timer classes work.

  2. Declare a field in your class of type SynchronizationContext and initialise it with SynchroinizationContext.Current. If your class is instantiated on the UI thread then that field will not be Nothing and you can use its Send/Post method.

jmcilhinney
  • 50,448
  • 5
  • 26
  • 46