Solved

VB.NET Threading Questions - Worker Thread Hanging the UI!

Posted on 2008-10-30
12
1,456 Views
Last Modified: 2013-11-07
Hi Experts,

I use threading all through a large application and have encountered a problem that i can't work out!

I am writing a single 'server' application to do a number of jobs for the company, this will involve mainly syncing up the website and doing some database work every few seconds. One of the other applications is checking SMS messages on a connected Nokia phone and handle them (i.e. send them off in an e-mail, write replies etc)

The issue is that every time i check the phone, the application hangs ... the obvious solution was to put the method into a thread that i simply fire off every 20 seconds.

Now that i have moved the method into a thread using the following:

Dim oThread As New Threading.Thread(AddressOf RefreshNokiaInbox)
oThread.Priority = Threading.ThreadPriority.Lowest
oThread.Start()

 Private Sub RefreshNokiaInbox()
        Dim oColl As HTFR.Objects.NokiaSMS.NokiaInternalStructures.NokiaObj_SMSItemCollection = HTFR.Objects.NokiaSMS.NokiaInternalStructures.NokiaObj_SMSItemCollection.GetBlankCollection
        Try
            'Tell the UI Thread that we are refreshing the Inbox
            Dim oDel As New del_SubCallbackNoArgs(AddressOf RefreshNokiaInbox_Callback_Started)
            HTFR.Objects.SharedElements.Objects.MDIForm.Invoke(oDel)

           'returns a collection of business objects containing the sms message details on the phone
            oColl = m_oNokiaPhoneItem.Inbox

        Catch ex As Exception
            HTFR.Objects.SharedElements.Methods.RaiseQuickError(ex)
        Finally
            'Tell the UI thread that we have completed
            Dim oDelComp As New del_RefreshInboxCallback(AddressOf RefreshNokiaInbox_Callback_Comp)
            HTFR.Objects.SharedElements.Objects.MDIForm.Invoke(oDelComp, oColl)
        End Try
    End Sub

Now, the issie is, that when this method is run ... the main UI still hangs!

My understanding is that if i put something in a thread, it doesn't touch the main UI until i make a callback with a delegate, so how can a worker thread lock up the main UI (but not the whole computer?)

The one thing i didn't want to do was write a different application for each job that i need to perform, surely firing off a thread for each 'job' is the same as having them running as different applications or does the OS handle the seperate programs better?
0
Comment
Question by:Gweep
  • 6
  • 3
  • 3
12 Comments
 
LVL 2

Expert Comment

by:Clausewitz
ID: 22841996
running it in another thread does not solve this problem. Your UI-Thread is still waiting for the result from the other thread.

Use an asynchronous callback and the UI won't be hanging any more.
http://msdn.microsoft.com/en-us/library/ms228969.aspx
0
 

Author Comment

by:Gweep
ID: 22842393
Eh?

What do you mean when you say that my UI thread is still waiting for the callback?

Are you saying that after calling the Thread.Start that my UI thread will hang and wait for the callback from the worker thread?

Surely while the UI is waiting for the callback from the worker thread it is also free to do any other processing on it because i havn't joined the threads?

Can you explain please?
0
 
LVL 2

Assisted Solution

by:Clausewitz
Clausewitz earned 100 total points
ID: 22842851
i thought you were calling the code you listed above from inside of your UI, sorry.
How do you call the Sub RefreshNokiaInbox? Are you sure it is called from the worker thread?
0
Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 22842867
I am often perplexed at what people do with threads...   =\

Please study the example below.  Each of the three buttons below shows a different approach.  I believe what you are doing is "equivalent" to what is happening in Button2.
Public Class Form1
 
    Public Delegate Sub DelayDelegate()
 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim T As New System.Threading.Thread(AddressOf Delay)
        T.Start()
    End Sub
 
    Private Sub Delay()
        ' do some "work"...main UI thread remains free and responsive
        System.Threading.Thread.Sleep(10000)
        MessageBox.Show("Done") ' <-- not really kosher to do from a thread...but we'll ignore this
    End Sub
 
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim T As New System.Threading.Thread(AddressOf DelayWithInvoke)
        T.Start()
    End Sub
 
    Private Sub DelayWithInvoke()
        ' consider the line of code below:
        Me.Invoke(New DelayDelegate(AddressOf Delay))
 
        ' Translation: Take the Delegate (which points to the Delay method), and run it on
        ' whatever thread owns "Me" (the Form).
 
        ' So even though this method, DelayWithInvoke(), is running in it's own thread,
        ' the Delay() method will be run on the main UI's thread causing it to lock up.
 
        ' What was the point of creating a new thread?!
 
        ' We essentially "negated" the whole point of a new thread by telling
        ' the system to take the "work" and do it on the thread we were trying to free up
        ' in the first place!
    End Sub
 
    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        Button3.Enabled = False
        Dim T As New System.Threading.Thread(AddressOf DelayWithInvokeUsedProperly)
        T.Start()
    End Sub
 
    Private Sub DelayWithInvokeUsedProperly()
        ' do some "work" on the THREAD WE CREATED
        System.Threading.Thread.Sleep(10000)
 
        ' Turn button3 back on using Invoke()...
        ' ...this needs to be done back on the main UI thread!
        ReEnableButton3()
    End Sub
 
    Private Sub ReEnableButton3()
        If Me.InvokeRequired Then
            Me.Invoke(New DelayDelegate(AddressOf ReEnableButton3))
        Else
            Button3.Enabled = True
        End If
    End Sub
 
End Class

Open in new window

0
 

Author Comment

by:Gweep
ID: 22843038
Heh .... no, what i am actually doing is closer to button 3.

The RefreshNokiaInbox sub would be run in the worker thread and then i use delegates to call back with progress and a final completed call, passing in the collection of business objects so a grid can be populated.

Give me a second and i'll write what i'm doing in your example....
0
 

Author Comment

by:Gweep
ID: 22843073
Here we go ...
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
        Dim T As New System.Threading.Thread(AddressOf DelayWithInvokeUsedProperly)
        T.Start()
    End Sub
 
    Private Sub RefreshNokiaInbox()
        Dim oColl As BusinessObjectCollection = NokiaPhoneClass.BlankCollection
        Try
            oColl = NokiaPhoneClass.Inbox
 
            System.Threading.Thread.Sleep(10000)
 
        Catch ex As Exception
            'handle the error
        Finally
            Dim oDel as del_Callback(Addressof CallbackSub)
            Me.invoke(odel, oColl)
        End Try
    End Sub
 
    Private Sub CallbackSub(ByVal Collection As BusinessObjectCollection)
        Grid.Datasource = Collection
    End Sub

Open in new window

0
 

Author Comment

by:Gweep
ID: 22843102
My problem is that while the worker thread is running the 'RefreshNokiaInbox' sub, the main UI will hang and become unresponsive.

I've done this a thousand times before while waiting for database calls etc without a problem but the Nokia Interop that i'm connecting too seems to slow it right down.

I guess my question is that how come my application hangs while i'm running it in a thread, and not the whole computer. This would elad me to believe that if i want to run many jobs on one computer it would be better to run them as seperate applications rather than one 'cleaner' application that does it all with threads

Would i be right?
0
 

Author Comment

by:Gweep
ID: 22843114
Sorry ... edit to the code example

Read the line
Dim T As New System.Threading.Thread(AddressOf DelayWithInvokeUsedProperly)

As
Dim T As New System.Threading.Thread(AddressOf RefreshNokiaInbox)
0
 
LVL 2

Expert Comment

by:Clausewitz
ID: 22843235
You have a coupling via Dim oColl As BusinessObjectCollection in your Sub RefreshNokiaInbox.

The business object is declared in your Sub running in the worker thread. When the UI-Thread wants to read and process it, it must wait until the worker thread is responding.
0
 
LVL 85

Accepted Solution

by:
Mike Tomlinson earned 400 total points
ID: 22843331
I would say the problem lies INSIDE NokiaPhoneClass then:

    oColl = NokiaPhoneClass.Inbox

Is this an external control that is dropped on your form?  Perhaps it was designed badly and is internally using Invoke() on it's parent container.   =\
0
 

Author Comment

by:Gweep
ID: 22843460
Clausewitz:
Could you explain to me what you mean by 'Coupling' please?

Idle_Mind:
The NokiaPhoneClass.Inbox is a wrapper that interfaces with a NokiaPhone via a serial lead. I know that this is where the problem lies, i just wanted to check that there wasn't any other way of calling a thread that would mean the worker thread was completely detached from the UI thread that called it.

Either way, i released a tweaked version and without the IDE, the program does not seem to lock up.

I'll still give you guys the points for effort tho ;)
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 22843475
Glad you figured it out...  =)
0

Featured Post

How our DevOps Teams Maximize Uptime

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us. Read the use case whitepaper.

Question has a verified solution.

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

Suggested Solutions

In my previous two articles we discussed Binary Serialization (http://www.experts-exchange.com/A_4362.html) and XML Serialization (http://www.experts-exchange.com/A_4425.html). In this article we will try to know more about SOAP (Simple Object Acces…
A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…

856 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