This is a classic issue when you use threading. The form instance variable has the <ThreadStatic
> attribute. Which causes it to create a new instance of the form when your code runs in a different thread. This can be hard to detect, the form isn't visible since you didn't call its Show() method. Not that it would work anyway, the thread isn't pumping a message loop.
Your workaround has problems of its own. There's a nasty bug in the Application.OpenForms implementation, it loses track of forms when their window gets recreated. Try this code for example:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Me.ShowInTaskbar = False
MessageBox.Show(String.Format("There are {0} form instances", Application.OpenForms.Count))
End Sub
There are many possible fixes for your problem. You could marshal the call to the UI thread with Control.Begin/Invoke(). Although that requires access to a form or control instance, a bit of a chicken-and-egg problem. Best thing to do is to simply pass the form instance to the helper's class constructor:
Class Helper
Private mForm As Form1
Public Sub New(ByVal frm As Form1)
mForm = frm
End Sub
End Class
Now you have the instance you need.