|
web
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Multithreading dilemmaI'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 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. 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. > 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. > > > > > 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. >> > >> >> >> "Dan" <nothing> wrote in message Dan,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) > 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. 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 > 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
How do you use GetProperty.SetValue with the index parameter?
EventHandler for late-bound COM object name parser How to check a string to see that it is a valid file name How to change the name of multiple textboxes CD Burning with VB.NET Silly syntactic question Opening Folder Browse Dialog On Client Side OT: Nant + VB 3.0 / 3.0 Extension Methods in VB 2008 Express? |
|||||||||||||||||||||||