Click here to Skip to main content
15,885,914 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
What i'm trying to do.
I'm Trying to add a Button to a Group box, with multi-threading but it gives me an error.
Error:
"Invoke or BeginInvoke cannot be called on a control until the window handle has been created."
Picture of the Error
http://i.imgur.com/FP5kKe4.png

The Code i wrote, but gives me an error, any help is appreciated.
VB
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim nt As New Thread(AddressOf BeforeAdding)
        nt.Start()
    End Sub
    Public Shared Function BeforeAdding()
        Dim rnd As New Random
        Dim str As String = rnd.Next(100, 10000)
        Dim btn As New Button
        AddControl(btn, str)
    End Function
    Public Shared Function AddControl(ctrl As Button, title As String)
            ctrl.Invoke(New MethodInvoker(Sub()
                                              ctrl.Dock = DockStyle.Left
                                              ctrl.Text = title
                                              Form1.GroupBox1.Controls.Add(ctrl)
                                          End Sub))
    End Function
Posted
Comments
[no name] 19-Sep-14 18:25pm    
You shouldn't be doing this on a non UI thread anyway.
Brucen Wayne 19-Sep-14 18:36pm    
Then when adding multiple controls in a certain amount of time will lag the whole application, i need a solution. How do i fix this error?
Sergey Alexandrovich Kryukov 19-Sep-14 19:07pm    
No, you can always do in some different thread through UI thread invocation, because such invocation actually delegate the call to the UI thread of the control you call Invoke on.
Only... you do it all correctly except one very tiny funny bug. Resolution is way too easy, just one word (Solution 1).
—SA
[no name] 19-Sep-14 19:53pm    
If you are adding so many controls dynamically that you are seeing your application "lag" then the problem is not your code, it's your design.

1 solution

This is not related to multithreading itself, it is related to UI invocation mechanism. In the System.Windows.Forms library, it is based on Windows message queue. Naturally, you can put anything to a queue of some windowed control only if this control already has a window handle. In your code, the instance ctrl is just created through its constructor. Naturally, it has no a window handle. Look at what you are doing: you are calling ctrl.Invoke on a control distance which is not even a part of the UI yet.

So, you are trying to use Control.Invoke well too early :-).

Resolution: replace ctrl.Invoke with Form1.Invoke. It is absolutely not important which control is added for invocation, it is any control which already participates in the UI of the thread you want to invoke the method to.

And please never use names like Form1 as well as any other auto-generated names. Such names violate Microsoft naming conventions. Always renames such object using some semantically meaningful names.

Background:
Please see my past answers on the topic:
Problem with Treeview Scanner And MD5[^],
Control.Invoke() vs. Control.BeginInvoke()[^].

—SA
 
Share this answer
 
v3

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900