Solved

Form not instantiated on inter-thread call OR how to load a form w/o making visible

Posted on 2006-11-06
4
241 Views
Last Modified: 2010-05-18

Hey, I have an MDI application with a child window that is sort of an "output" window.  I also have buttons that start processes on background threads, and sometimes when the process is done it needs to send text to the output window.  So I made my Write functions thread-safe as follows (pretty much parroting another answer from this great site -- I don't understand this as well as I should).

In my OutputWindow form:

    Public Sub Write(ByVal txt As String)
        AppendLine(txt)
    End Sub

    Delegate Sub SetTextCallback(ByVal [text] As String)

    Private Sub AppendLine(ByVal txt As String)

        ' InvokeRequired required compares the thread ID of the
        ' calling thread to the thread ID of the creating thread.
        ' If these threads are different, it returns true.

        If Me.RichTextBox1.InvokeRequired Then
            Dim d As New SetTextCallback(AddressOf RawAppendLine)
            Me.Invoke(d, New Object() {txt})
        Else
            RawAppendLine(txt)
        End If

    End Sub

    Private Sub RawAppendLine(ByVal txt As String)

        RichTextBox1.AppendText(vbCrLf + txt)
        ScrollToEnd()

    End Sub

Now... when I start my application, I *New* the form but I do not set Visible=True (which I think means the form and constituent controls do not actually get loaded) unless the user has set an option that he wants it visible on startup.  If this option is not set and it is not made visible, calls to Write from an alternate thread fail with the following exception:

"Invoke or BeginInvoke cannot be called on a control until the window handle has been created."

Now, BEFORE this error the program uses the Write function at startup from the same thread (for messages like "Program started") and when the user eventually shows the window it appears with all the messages, which seems to mean the RichTextBox was loaded.  So this succeeds:

1) Starts invisible (New but no Visible=True)
2) Write from same thread
3) User calls Visible=True (from menu item) (previous writes are visible, which seems to mean it was instantiated?)
4) Write from other thread

And this fails

1) Starts invisible (New but no Visible=True)
2) Write from same thread  (why didn't this instantiate the control, i.e., "create the window handle"?)
3) Write from other thread   <-- above exception!

Anybody have any good theories which fit these observations??  I'd like to (1) fix this and (2) understand a little better.  

Thanks in advance...






0
Comment
Question by:riceman0
  • 2
4 Comments
 
LVL 48

Expert Comment

by:AlexFM
ID: 17881954
   Public Sub Write(ByVal txt As String)
        AppendLine(txt)
    End Sub

In this function you can test whether form handle is created. You can subscribe to Control.HandleCreated Event and set some flag in the handler for this. If form is not created yet, accumulate all text in some container for example, StringBuilder or List<String>.
When form is shown first time, show information from container to RichTextBox1. From this moment, Write function can call AppendLine and safely use Invoke and RichTextBox1.

Unfortunately, .NET doesn't allow to create valid visible form - you cannot work normally with form controls and execute Invoke unless form is shown first time.
0
 

Author Comment

by:riceman0
ID: 17882021

Oh, man: subscribing to events, creating a flag.  

Seems like a bad oversight that they didn't allow you to start a window invisible, would save a lot of headache.

Question before I try all that... I suspect my window HAS been created, since the previous same-thread Write calls work, yes?  Why then this error?



0
 
LVL 48

Accepted Solution

by:
AlexFM earned 500 total points
ID: 17882867
Well, possibly Form allows to set control properties before handle is created. But Invoke cannot work before handle is created. Handle is created only when Form.Show function is called, and this immediately makes form visible.
I think that when form is hidden (after it was shown initially), Invoke can fail as well. At least I know, that when form is hidden and shown again, its handle may change.
So, to make this working, I suggest the following algorithm (pseudo-code):

dim handleExists as boolean = false

HandleCreated:
    handleExists = true;
    Add text from container to RichTextBox
    Clear container

HandleDestroyed:
    handleExists = false;

AppendLine:
    if handle doesn't exist: add line to container
    else: existing code
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

I think the Typed DataTable and Typed DataSet are very good options when working with data, but I don't like auto-generated code. First, I create an Abstract Class for my DataTables Common Code.  This class Inherits from DataTable. Also, it can …
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
Need to grow your business through quality cloud solutions? With everything required to build a cloud platform and solution, you may feel like the distance between you and the cloud is quite long. Help is here. Spend some time learning about the Con…
A company’s greatest vulnerability is their email. CEO fraud, ransomware and spear phishing attacks are the no1 threat to a company’s security. Cybercrime is responsible for the largest loss of money to companies today with losses projected to r…

947 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now