I have a simple form which starts a new thread, and this thread displays the value of a control (TextBox)

Form contains:
TextBox with default value of "Default"
StartButton which starts a new thread

Form:

Public Class Form
    Private Sub StartButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            'The reason i declare the thread like this is because it allows me to pass parameters to the DisplayBox() sub, or any other sub, which i need in my main application.
            Dim t As New Thread(DirectCast(Sub() DisplayBox(), ThreadStart))
            t.Start()
    End Sub

   Public Sub DisplayBox()
            MsgBox(TextBox1.text)
   End Sub
End Class

Simple enough. I start it, replace the "Default" text in my TextBox to anything I want, hit start, and my new thread MsgBox's me the new value.

Now i try something more useful to me. I put the DisplayBox() sub into it's own module. Then i run the program again, and this time i get this error from the MsgBox in the the module:

"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."

Now i don't exactly understand the error. Especially the part about creating a form. But i did some googling and i found out how to set the new thread to running in a single-threaded apartment:

"t.SetApartmentState(ApartmentState.STA)"

Seems to work, the previous error disappears. But now when i start the thread, with DisplayBox() still being in it's own module, MsgBox always displays the same "Default" value from the TextBox in the Form. Whatever i change the value of Textbox1.Text to, and then run the thread, the MsgBox will always return it's initial value "Default".

Sorry If I'm not very clear, I'm up very late trying to figure this out. If anyone could explain to me why this is occurring and why i got that original error before, i would be very grateful. Thanks.

Recommended Answers

All 4 Replies

I have read that article. The problem is that Form1.InvokeRequired always returns false. There doesn't seem to be conflict between my threads over access to the control.

It seems like when my thread is running code from a different module, it's communicating with a hidden copy of the Form.

For instance, i can create the following Sub on a different module

Private Sub TestThread()
Form1.Textbox.Text = "TestTestTest" 'Changes the text from the initial value "Default"
MsgBox(Form1.Textbox.Text)
End Sub

MsgBox returns the changed value of the Textbox: "TestTestTest". But when i look at my actual form, the value has not changed. It's still "Default".

EDIT: Here is a picture to explain better: [img]http://img37.imageshack.us/img37/2207/41409617.jpg[/img]

I SOLVED IT.

The problem was that when i was referencing Form1, it would actually create a new hidden form and make all the changes with that. You must find a new way to reference the form. Such as:

Dim main As Form1 = CType(Application.OpenForms(0), Form1)
MsgBox(main.Textbox.Text)

Now it works, and gives me an error about accessing a control from a thread it was not created in, and this is where i need to use invoke to safely call it.

Thanks anyway.

EDIT: I'm taking all the credit. This guy here solved it:
http://stackoverflow.com/questions/273639/force-multi-threaded-vb-net-class-to-display-results-on-a-single-form

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.