Passing data to different UI threads

Viewed 60

As an old mainframe systems programmer, I'm not specialised at all in OO thinking, nor in Visual Basic. A former colleague and I wrote a VB program (named FotoDB) to manage and present our family&holyday photos. We have kind of a database with descriptions and GPS coordinates for all of them.

FotoDB can also work in "presentation mode" and then I'd like to also show the OpenStreetMap of the area where the active photo was taken. I already found out how to use Leaflet.js to display the map in a WebBrowser object.
A first problem I encountered when I tried to use a WebBrowser object was that I got:

cannot be instantiated because the current thread is not in a single-threaded apartment.

Our FotoDB program must remain defined multi-threading (I think): it uses a BackgroundWorker for some things, and is also listening for 2 control files that might be changed by Notepad (or alike).

So, I abandoned the idea of adding the map as a small item on the main screen of FotoDB, but use another form for the WebBrowser object, and I start that in a new STA-mode thread:

  mapThread = New Thread(AddressOf form4MapShow)
  mapThread.SetApartmentState(ApartmentState.STA) 
  mapThread.Start()
End Sub
Private Sub form4MapShow()
  Form4map.Show()
End Sub

That works fine, I can display a section of the OpenStreetMap in my "Form4map".

I still have 2 problems (probably reduceable to 1 problem)

  1. I need to pass the GPS coordinates from the main program to the thread in which From4map runs
  2. When the end-user selects a new photo to view, the main program must pass the new coordinates to Form4map

I've been reading a bit about Delegate, but without understanding it completely. I found examples about updating a ListView from another thread and tried to mimic it (when a new photo is displayed in the main frame, send its GPS coordinates to a text field on Form4map), So I coded (as a basic test):

  NieuweFoto(Form4map.txtNwFoto, "Nieuw " & Now.ToLocalTime)
End Sub
Public Delegate Sub newPhotoInvoker(ByVal txt As TextBox, ByVal itemtext As String)

Public Sub NieuweFoto(ByVal txt As TextBox, ByVal gpsInfo As String)
  If Form4map.txtNwFoto.InvokeRequired Then
    Form4map.txtNwFoto.Invoke(New newPhotoInvoker(AddressOf NieuweFoto), txt, gpsInfo)
  Else
    txt.Text = gpsInfo
  End If
End Sub

But, now I get a similar error as at the start:

An error occurred creating the form. See Exception.InnerException for details.
The error is: ActiveX control '8856f961-340a-11d0-a96b-00c04fd705a2' cannot be instantiated because the current thread is not in a single-threaded apartment.

So I'm stuck. Is there an easy solution?

0 Answers
Related