Home All Groups Group Topic Archive Search About

Multithreading dilemma

Author
22 Nov 2007 6:19 PM
dan artuso
Hi,
I'm having a problem implementing multithreading in
an app that basically recurses through the path passed to it.

The main interface is basically an explorer knockoff and the user can
perform certain
tasks on all files and directories within their selection.

The problem is that for a little bit the main UI is responsive after spawing
the thead but continued
use of it causes both the main thread and the worker thread to freeze up. If
we don't touch the UI at all,
everything works :-)
Note that we are not trying to update any form controls from the worker
thread!

I'll post what code I think is relevant and anyone who has any ideas, please
let us know!
Thanks

Dan

here is code in the form:

Private Sub cmdStart_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles cmdStart.Click
    'for this quick search, the only pattern passed willl be the PermPattern

    Dim objPerms As New PermPattern

    'we still need a list of patterns because the Search constructor expects
it.

    Dim thisPatternList As New List(Of Pattern)

    'this is for each path in the listview

    Dim strPaths As New List(Of String)

    Dim csitems As New List(Of CShItem)

    objPerms.state = PermPattern.permissions.accessDenied +
PermPattern.permissions.noAdmins + _

    PermPattern.permissions.noSystem + PermPattern.permissions.notAGroup + _

    PermPattern.permissions.pathTooLong

    thisPatternList.Add(objPerms)

                For Each lvItem As ListViewItem In Me.lvDirs.Items

                    Dim csItem As New CShItem(lvItem.Text)

                    csitems.Add(csItem)

            Next

'our search object

    Dim objSearch As New Search(thisPatternList, csitems, Me)

        objSearch.Start()


End Sub


Here is the code in the Search class:


        'rference to calling form

        Private m_clientApp As Form

        'create a delegate that will call back into the main form

        Private Delegate Sub ProcessResults(ByVal objSearch As Search)

        'create an object for the delegate

        Private m_callMainForm As ProcessResults


Constructor:


Sub New(ByVal Patterns As List(Of Pattern), ByVal cshItems As List(Of
CShItem), ByVal callingForm As Form)

    m_patterns = Patterns

    m_results = New List(Of Result)

    m_cshItems = cshItems

    m_clientApp = callingForm

    'dim all possible form variables

    Dim policyAudit As fPolicyAudit

    Dim changeOwner As fChangeOwner

    'try to cast

    policyAudit = TryCast(callingForm, fPolicyAudit)

    changeOwner = TryCast(callingForm, fChangeOwner)

    If Not IsNothing(policyAudit) Then

        m_callMainForm = AddressOf policyAudit.Processresults

    End If

End Sub

        Protected InnerThread As New Thread(AddressOf Me.SearchFiles)

Public Sub Start()

    InnerThread.SetApartmentState(ApartmentState.STA)

    InnerThread.IsBackground = True

    InnerThread.Priority = ThreadPriority.BelowNormal

    InnerThread.Start()

End Sub

'here is the routine that starts on a seperate thread. Basically, for each
path passed in, it calls WorkWithItems which recurses through files and
folders

Public Sub SearchFiles()

            Debug.Print("SearchFiles: " &
System.Threading.Thread.CurrentThread.ManagedThreadId.ToString)

        m_results.Clear()

        For Each csItem As CShItem In m_cshItems

                WorkWithItems(csItem)

        Next



Debug.Print("about to callback")

'call back to calling form passing the Search object so results can be
processed

m_clientApp.Invoke(m_callMainForm, Me)

End Sub

Author
22 Nov 2007 8:34 PM
AMercer
You should be able to start a compute bound thread (eg For loops that churn
for about 10 seconds) and still have a responsive gui while the thread is
running.  When I do this, I don't call SetApartmentState, I do set
IsBackground true as you do, and I leave Priority unchanged (BelowNormal
should be unnecessary).  My first suggestion is to verify that you can do
this simple threading exercise.  I have no experience with setting the
apartment state, ergo I am suspicious of it.

Second, your description makes it plausible that a resource is being
consumed.  Run your program and watch your process's task manager line.  Make
sure everything that can be viewed is visible.  Watch for a steadily rising
number like the handle count.  Alternatively, use a perf tool that you are
comfortable with.

Third, as a stab in the dark and a curiosity, I would insert a Sleep(50
milliseconds) for each file you process.  Is the gui more responsive with the
sleeps?  Does the freeze up still happen?  IMO this is unlikely to help, but
it is easy to try.
Author
22 Nov 2007 10:16 PM
Dan
Hi
Thanks for the replies.
This is a difficult thing to troubleshoot I know.

I tried putting the Sleep(50) in and no difference.

COM is involved in the Search routine.
WorkWithItems(ByVal csItem As CShItem)



CShItem is a class we use in the project that uses COM.

We didn't write this and there is tons of code in it.

I have a feeling this may be our problem. The array of CShItems gets passed
into the Search object before the new thread is started.

Altough I don't know why everything would freeze up simply by using the
MainForm which is executing on a different thread.

I also kept an eye on the resources in Task Manager and nothing was out of
the ordinary.

I appreciate the effort but I suspect we'll have to fix this thing on our
own!

Thanks again!

Dan


Show quoteHide quote
"AMercer" <AMer***@discussions.microsoft.com> wrote in message
news:97085625-AA09-4F46-8B19-B087C4A82F35@microsoft.com...
> You should be able to start a compute bound thread (eg For loops that
> churn
> for about 10 seconds) and still have a responsive gui while the thread is
> running.  When I do this, I don't call SetApartmentState, I do set
> IsBackground true as you do, and I leave Priority unchanged (BelowNormal
> should be unnecessary).  My first suggestion is to verify that you can do
> this simple threading exercise.  I have no experience with setting the
> apartment state, ergo I am suspicious of it.
>
> Second, your description makes it plausible that a resource is being
> consumed.  Run your program and watch your process's task manager line.
> Make
> sure everything that can be viewed is visible.  Watch for a steadily
> rising
> number like the handle count.  Alternatively, use a perf tool that you are
> comfortable with.
>
> Third, as a stab in the dark and a curiosity, I would insert a Sleep(50
> milliseconds) for each file you process.  Is the gui more responsive with
> the
> sleeps?  Does the freeze up still happen?  IMO this is unlikely to help,
> but
> it is easy to try.
>
Author
22 Nov 2007 11:54 PM
AMercer
From your info below, I suggest you split your single process solution into
two processes.  Have your gui process launch a new process to do the work
that is apparently causing the problem and that contains the software that is
difficult or impossible to fix.  When it has done its work, the process
terminates, and its ill effects will be isolated in a process that is
terminating.  Starting the process should be easy enough - all you need to
give the new process is a path.  If there are any results that it produces,
you will need to come up with a way to get the data back into the gui process.


Show quoteHide quote
"Dan" wrote:

> Hi
> Thanks for the replies.
> This is a difficult thing to troubleshoot I know.
>
> I tried putting the Sleep(50) in and no difference.
>
> COM is involved in the Search routine.
> WorkWithItems(ByVal csItem As CShItem)
>
>
>
> CShItem is a class we use in the project that uses COM.
>
> We didn't write this and there is tons of code in it.
>
> I have a feeling this may be our problem. The array of CShItems gets passed
> into the Search object before the new thread is started.
>
> Altough I don't know why everything would freeze up simply by using the
> MainForm which is executing on a different thread.
>
> I also kept an eye on the resources in Task Manager and nothing was out of
> the ordinary.
>
> I appreciate the effort but I suspect we'll have to fix this thing on our
> own!
>
> Thanks again!
>
> Dan
>
>
> "AMercer" <AMer***@discussions.microsoft.com> wrote in message
> news:97085625-AA09-4F46-8B19-B087C4A82F35@microsoft.com...
> > You should be able to start a compute bound thread (eg For loops that
> > churn
> > for about 10 seconds) and still have a responsive gui while the thread is
> > running.  When I do this, I don't call SetApartmentState, I do set
> > IsBackground true as you do, and I leave Priority unchanged (BelowNormal
> > should be unnecessary).  My first suggestion is to verify that you can do
> > this simple threading exercise.  I have no experience with setting the
> > apartment state, ergo I am suspicious of it.
> >
> > Second, your description makes it plausible that a resource is being
> > consumed.  Run your program and watch your process's task manager line.
> > Make
> > sure everything that can be viewed is visible.  Watch for a steadily
> > rising
> > number like the handle count.  Alternatively, use a perf tool that you are
> > comfortable with.
> >
> > Third, as a stab in the dark and a curiosity, I would insert a Sleep(50
> > milliseconds) for each file you process.  Is the gui more responsive with
> > the
> > sleeps?  Does the freeze up still happen?  IMO this is unlikely to help,
> > but
> > it is easy to try.
> >
>
>
>
Author
23 Nov 2007 1:38 PM
dan artuso
You know, I was just thinking about the 'good old days' in VB6 where I would
simulate a thread with an ActiveX exe, spawning another process. Always
worked like a charm!

Thanks for your suggestions.

Dan


Show quoteHide quote
"AMercer" <AMer***@discussions.microsoft.com> wrote in message
news:0CF42B28-E88D-4851-87B1-D3683DD4C7BA@microsoft.com...
> From your info below, I suggest you split your single process solution
> into
> two processes.  Have your gui process launch a new process to do the work
> that is apparently causing the problem and that contains the software that
> is
> difficult or impossible to fix.  When it has done its work, the process
> terminates, and its ill effects will be isolated in a process that is
> terminating.  Starting the process should be easy enough - all you need to
> give the new process is a path.  If there are any results that it
> produces,
> you will need to come up with a way to get the data back into the gui
> process.
>
>
> "Dan" wrote:
>
>> Hi
>> Thanks for the replies.
>> This is a difficult thing to troubleshoot I know.
>>
>> I tried putting the Sleep(50) in and no difference.
>>
>> COM is involved in the Search routine.
>> WorkWithItems(ByVal csItem As CShItem)
>>
>>
>>
>> CShItem is a class we use in the project that uses COM.
>>
>> We didn't write this and there is tons of code in it.
>>
>> I have a feeling this may be our problem. The array of CShItems gets
>> passed
>> into the Search object before the new thread is started.
>>
>> Altough I don't know why everything would freeze up simply by using the
>> MainForm which is executing on a different thread.
>>
>> I also kept an eye on the resources in Task Manager and nothing was out
>> of
>> the ordinary.
>>
>> I appreciate the effort but I suspect we'll have to fix this thing on our
>> own!
>>
>> Thanks again!
>>
>> Dan
>>
>>
>> "AMercer" <AMer***@discussions.microsoft.com> wrote in message
>> news:97085625-AA09-4F46-8B19-B087C4A82F35@microsoft.com...
>> > You should be able to start a compute bound thread (eg For loops that
>> > churn
>> > for about 10 seconds) and still have a responsive gui while the thread
>> > is
>> > running.  When I do this, I don't call SetApartmentState, I do set
>> > IsBackground true as you do, and I leave Priority unchanged
>> > (BelowNormal
>> > should be unnecessary).  My first suggestion is to verify that you can
>> > do
>> > this simple threading exercise.  I have no experience with setting the
>> > apartment state, ergo I am suspicious of it.
>> >
>> > Second, your description makes it plausible that a resource is being
>> > consumed.  Run your program and watch your process's task manager line.
>> > Make
>> > sure everything that can be viewed is visible.  Watch for a steadily
>> > rising
>> > number like the handle count.  Alternatively, use a perf tool that you
>> > are
>> > comfortable with.
>> >
>> > Third, as a stab in the dark and a curiosity, I would insert a Sleep(50
>> > milliseconds) for each file you process.  Is the gui more responsive
>> > with
>> > the
>> > sleeps?  Does the freeze up still happen?  IMO this is unlikely to
>> > help,
>> > but
>> > it is easy to try.
>> >
>>
>>
>>
Author
24 Nov 2007 3:27 AM
Michael D. Ober
"Dan" <nothing> wrote in message
news:uhuvbVVLIHA.3516@TK2MSFTNGP02.phx.gbl...
> Hi
> Thanks for the replies.
> This is a difficult thing to troubleshoot I know.
>
> I tried putting the Sleep(50) in and no difference.
>
> COM is involved in the Search routine.
> WorkWithItems(ByVal csItem As CShItem)
>

Dan,

Given that COM is indeed involved, you're best bet will be to split the
application into two apps.  COM objects aren't Win32 (or .NET) thread aware
and really need to be in seperate processes.  This is even true with the
Apartment model.  All the Apartment model does is prevents the COM object
from sharing it's internal data structures across multiple processes.
Instead the Apartment model COM objects will request the calling process
allocate memory - once.

Mike.
Author
22 Nov 2007 9:26 PM
Michael D. Ober
Dan,

Don't use SetApartmentState unless you are using COM Interop.  Apartments
are part of the COM multithreading interface.  I suspect removing this one
line will fix your performance problems.

Mike Ober.


Show quoteHide quote
"dan artuso" <dartuso@NOSPAMpagepearls.com> wrote in message
news:OOFB0QTLIHA.5580@TK2MSFTNGP02.phx.gbl...
> Hi,
> I'm having a problem implementing multithreading in
> an app that basically recurses through the path passed to it.
>
> The main interface is basically an explorer knockoff and the user can
> perform certain
> tasks on all files and directories within their selection.
>
> The problem is that for a little bit the main UI is responsive after
> spawing the thead but continued
> use of it causes both the main thread and the worker thread to freeze up.
> If we don't touch the UI at all,
> everything works :-)
> Note that we are not trying to update any form controls from the worker
> thread!
>
> I'll post what code I think is relevant and anyone who has any ideas,
> please let us know!
> Thanks
>
> Dan
>
> here is code in the form:
>
> Private Sub cmdStart_Click(ByVal sender As System.Object, ByVal e As
> System.EventArgs) Handles cmdStart.Click
>    'for this quick search, the only pattern passed willl be the
> PermPattern
>
>    Dim objPerms As New PermPattern
>    'we still need a list of patterns because the Search constructor
> expects it.
>    Dim thisPatternList As New List(Of Pattern)
>    'this is for each path in the listview
>    Dim strPaths As New List(Of String)
>    Dim csitems As New List(Of CShItem)
>    objPerms.state = PermPattern.permissions.accessDenied +
> PermPattern.permissions.noAdmins + _
>    PermPattern.permissions.noSystem + PermPattern.permissions.notAGroup +
> _
>    PermPattern.permissions.pathTooLong
>    thisPatternList.Add(objPerms)
>
>                For Each lvItem As ListViewItem In Me.lvDirs.Items
>                    Dim csItem As New CShItem(lvItem.Text)
>                    csitems.Add(csItem)
>            Next
>
> 'our search object
>
>    Dim objSearch As New Search(thisPatternList, csitems, Me)
>        objSearch.Start()
> End Sub
>
>
> Here is the code in the Search class:
>
>
>        'rference to calling form
>
>        Private m_clientApp As Form
>        'create a delegate that will call back into the main form
>        Private Delegate Sub ProcessResults(ByVal objSearch As Search)
>        'create an object for the delegate
>        Private m_callMainForm As ProcessResults
>
> Constructor:
> Sub New(ByVal Patterns As List(Of Pattern), ByVal cshItems As List(Of
> CShItem), ByVal callingForm As Form)
>
>    m_patterns = Patterns
>    m_results = New List(Of Result)
>    m_cshItems = cshItems
>    m_clientApp = callingForm
>    'dim all possible form variables
>
>    Dim policyAudit As fPolicyAudit
>    Dim changeOwner As fChangeOwner
>    'try to cast
>    policyAudit = TryCast(callingForm, fPolicyAudit)
>    changeOwner = TryCast(callingForm, fChangeOwner)
>
>    If Not IsNothing(policyAudit) Then
>        m_callMainForm = AddressOf policyAudit.Processresults
>    End If
> End Sub
>
>        Protected InnerThread As New Thread(AddressOf Me.SearchFiles)
>
> Public Sub Start()
>    InnerThread.SetApartmentState(ApartmentState.STA)
>    InnerThread.IsBackground = True
>    InnerThread.Priority = ThreadPriority.BelowNormal
>    InnerThread.Start()
> End Sub
>
> 'here is the routine that starts on a seperate thread. Basically, for each
> path passed in, it calls WorkWithItems which recurses through files and
> folders
>
> Public Sub SearchFiles()
>
>            Debug.Print("SearchFiles: " &
> System.Threading.Thread.CurrentThread.ManagedThreadId.ToString)
>        m_results.Clear()
>        For Each csItem As CShItem In m_cshItems
>                WorkWithItems(csItem)
>        Next
>
> Debug.Print("about to callback")
>
> 'call back to calling form passing the Search object so results can be
> processed
> m_clientApp.Invoke(m_callMainForm, Me)
> End Sub
>
Author
23 Nov 2007 7:26 PM
Cor Ligthert[MVP]
Dan,

What is your goal, using multithreading or making a good solution.

In my idea we see often here people who only want multithreading because it
sounds so interesting.

Mutlithreading is only in few circumstances (and they are there for sure)
giving benefits.

As soon as your processor or a port is fulltime busy, you have no benefits,
only longer processing time and difficulties not to restart a thread because
the user just pushes a button.

Cor