Quick 500 - Need help on Threading; a nice puzzle for you guru's :)


I'm been working on a CommandButton UserControl that is passed a stored procedure. When a button is pressed, It calls the Results from the database and then displays the information in a seperate form which is then aligned to the UserControl.

This is all working until today when i decided that i wanted the Database call which takes a few seconds to be done in a seperate thread... Everything is working fine, but by the time the Call finishes the forms are flashing visible then disappearing.

I've tracked the point in which the forms disappear, there are no dispose calls being made or anything like that, unfortunatly this is where it gets interesting... the Forms are disappearing when the cursor ends a subroutine.

I've made a simple peice of code for you guys to compile
You need to breakpoint the 'End Sub' which i've clearly marked

Do the following....
Make a normal Windows Project
Add another project to the solution - Select Windows Control Library
In the new UserControl... Draw a new button (no need to rename)

now go into the Code of the USer control and Paste the Following:


        Private Delegate Sub DataSet_WorkCompleted(ByVal ObjRows() As DataRow)
        Private m_ResultCallback As DataSet_WorkCompleted
        Private ObjSearchResults As SearchResults
    Private WithEvents ObjFrmResults As New Form1

    Private Sub Cmd_Search_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        'The Search button was Clicked.. Open the Wrapper and Populate it with the Parameters and SP info

            m_ResultCallback = AddressOf Populate_Results
            ObjSearchResults = New SearchResults(m_ResultCallback)
            Dim ObjThread As New Threading.Thread(AddressOf ObjSearchResults.Search)

        Catch ex As Exception
            'Error stuff
        End Try
    End Sub

    Private Sub Populate_Results(ByVal ObjDataRows() As Data.DataRow)
        'Show the form
        ObjFrmResults.TopMost = True
    End Sub

    Private Class SearchResults
        Private m_CallBackThread As DataSet_WorkCompleted

        Public Sub New(ByRef CallBackWhenCompleted As DataSet_WorkCompleted)
            m_CallBackThread = CallBackWhenCompleted
        End Sub
        Public Sub Search()
            Dim ObjRow(5) As DataRow

            'This is where the DB call goes...

            'By now the ObjRow would be populated also...


        End Sub 'BREAKPOINT HERE <-------
    End Class

Now... Rebuild the solution and paste the Usercontrol onto the first project's form....

After breakpointing the 'End Sub' that i've marked.... Run the project and click the Button, You should see a new form (topmost for debug) appear on top of the existing form and the breakpoint kick off...

This is where my results are displayed.... but as soon as you Step through so the cursor goes past the End Sub, the Form disappears

I think this is something to do with the GC killing it all off because the form is obviously running on the same thread (my best guess) but i can't figure out how to make the form stay :/

If you can figure out this little puzzle the 500 is yours :D

Thanks in Advance
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

The problem is that your created thread is trying to alter the user interface.  Only the main thread can alter the user interface ( Private Sub Populate_Results)

One way around this is the use of delegates - when the data has been retrieved, having the created thread call ObjFrmResults.Invoke(Delegate), which would force the called delegate to run under the main thread.

The other way is to create a delegate and use it's BeginInvoke and EndInvoke.
Here's an example on how to do it - I am not using the class you created in your code above, so it's a bit simpler:
    'Define a delegate Structure
    Private Delegate Function delSearch() As DataRow()
    'Create a Delegate Object of type delSearch
    Private d As New delSearch(AddressOf GetData)
    Sub Cmd_Search_Click()  'Whatever event should start the ball rolling.
        'The following cruns GetData on a seperate thread, and when
        'done executing, calls HasData on the current thread.
        d.BeginInvoke(New AsyncCallback(AddressOf HasData), Nothing)
    End Sub
    'This function will run on a seperate thread.
    Function GetData() As DataRow()
        '... Get Data Here ..., return DataRows...
        'Return SomeRows
    End Function
    Sub HasData(ByVal ar As IAsyncResult)
        'The next line retrieves the datarows from the non-ui thread...
        Dim myDataRows() As DataRow = d.EndInvoke(ar)
        ObjFrmResults.TopMost = True
    End Sub

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Cloud9_UserAuthor Commented:
Brilliant.... the First example solved my Problem, except in my Actual code i'm passing the UserControl anyway... So i just did UserControl.Invoke

It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.