Solved

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

Posted on 2008-10-30
12
1,446 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
 
LVL 85

Expert Comment

by:Mike Tomlinson
Comment Utility
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
Comment Utility
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
Comment Utility
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
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 

Author Comment

by:Gweep
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
Glad you figured it out...  =)
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

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…
Parsing a CSV file is a task that we are confronted with regularly, and although there are a vast number of means to do this, as a newbie, the field can be confusing and the tools can seem complex. A simple solution to parsing a customized CSV fi…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

728 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

13 Experts available now in Live!

Get 1:1 Help Now